Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/srv/loader/main.c

    r1ea99cc rffa2c8ef  
    5050#include <fcntl.h>
    5151#include <sys/types.h>
    52 #include <ipc/ipc.h>
    5352#include <ipc/services.h>
    5453#include <ipc/loader.h>
     
    5857#include <errno.h>
    5958#include <async.h>
    60 #include <string.h>
     59#include <str.h>
    6160#include <as.h>
    6261
     
    6665#define DPRINTF(...)
    6766
    68 void program_run(void *entry, pcb_t *pcb);
    69 
    7067/** Pathname of the file that will be loaded */
    7168static char *pathname = NULL;
     
    7370/** The Program control block */
    7471static pcb_t pcb;
     72
     73/** Current working directory */
     74static char *cwd = NULL;
    7575
    7676/** Number of arguments */
     
    9494
    9595/** Used to limit number of connections to one. */
    96 static bool connected;
     96static bool connected = false;
    9797
    9898static void ldr_get_taskid(ipc_callid_t rid, ipc_call_t *request)
     
    104104        task_id = task_get_id();
    105105       
    106         if (!ipc_data_read_receive(&callid, &len)) {
    107                 ipc_answer_0(callid, EINVAL);
    108                 ipc_answer_0(rid, EINVAL);
     106        if (!async_data_read_receive(&callid, &len)) {
     107                async_answer_0(callid, EINVAL);
     108                async_answer_0(rid, EINVAL);
    109109                return;
    110110        }
     
    113113                len = sizeof(task_id);
    114114       
    115         ipc_data_read_finalize(callid, &task_id, len);
    116         ipc_answer_0(rid, EOK);
    117 }
    118 
     115        async_data_read_finalize(callid, &task_id, len);
     116        async_answer_0(rid, EOK);
     117}
     118
     119/** Receive a call setting the current working directory.
     120 *
     121 * @param rid
     122 * @param request
     123 */
     124static void ldr_set_cwd(ipc_callid_t rid, ipc_call_t *request)
     125{
     126        char *buf;
     127        int rc = async_data_write_accept((void **) &buf, true, 0, 0, 0, NULL);
     128       
     129        if (rc == EOK) {
     130                if (cwd != NULL)
     131                        free(cwd);
     132               
     133                cwd = buf;
     134        }
     135       
     136        async_answer_0(rid, rc);
     137}
    119138
    120139/** Receive a call setting pathname of the program to execute.
     
    125144static void ldr_set_pathname(ipc_callid_t rid, ipc_call_t *request)
    126145{
    127         ipc_callid_t callid;
    128         size_t len;
    129         char *name_buf;
    130        
    131         if (!ipc_data_write_receive(&callid, &len)) {
    132                 ipc_answer_0(callid, EINVAL);
    133                 ipc_answer_0(rid, EINVAL);
    134                 return;
    135         }
    136        
    137         name_buf = malloc(len + 1);
    138         if (!name_buf) {
    139                 ipc_answer_0(callid, ENOMEM);
    140                 ipc_answer_0(rid, ENOMEM);
    141                 return;
    142         }
    143        
    144         ipc_data_write_finalize(callid, name_buf, len);
    145         ipc_answer_0(rid, EOK);
    146        
    147         if (pathname != NULL) {
    148                 free(pathname);
    149                 pathname = NULL;
    150         }
    151        
    152         name_buf[len] = '\0';
    153         pathname = name_buf;
     146        char *buf;
     147        int rc = async_data_write_accept((void **) &buf, true, 0, 0, 0, NULL);
     148       
     149        if (rc == EOK) {
     150                if (pathname != NULL)
     151                        free(pathname);
     152               
     153                pathname = buf;
     154        }
     155       
     156        async_answer_0(rid, rc);
    154157}
    155158
     
    161164static void ldr_set_args(ipc_callid_t rid, ipc_call_t *request)
    162165{
    163         ipc_callid_t callid;
    164         size_t buf_size, arg_size;
    165         char *p;
    166         int n;
    167        
    168         if (!ipc_data_write_receive(&callid, &buf_size)) {
    169                 ipc_answer_0(callid, EINVAL);
    170                 ipc_answer_0(rid, EINVAL);
    171                 return;
    172         }
    173        
    174         if (arg_buf != NULL) {
    175                 free(arg_buf);
    176                 arg_buf = NULL;
    177         }
    178        
    179         if (argv != NULL) {
    180                 free(argv);
    181                 argv = NULL;
    182         }
    183        
    184         arg_buf = malloc(buf_size + 1);
    185         if (!arg_buf) {
    186                 ipc_answer_0(callid, ENOMEM);
    187                 ipc_answer_0(rid, ENOMEM);
    188                 return;
    189         }
    190        
    191         ipc_data_write_finalize(callid, arg_buf, buf_size);
    192        
    193         arg_buf[buf_size] = '\0';
    194        
    195         /*
    196          * Count number of arguments
    197          */
    198         p = arg_buf;
    199         n = 0;
    200         while (p < arg_buf + buf_size) {
    201                 arg_size = str_size(p);
    202                 p = p + arg_size + 1;
    203                 ++n;
    204         }
    205        
    206         /* Allocate argv */
    207         argv = malloc((n + 1) * sizeof(char *));
    208        
    209         if (argv == NULL) {
    210                 free(arg_buf);
    211                 ipc_answer_0(rid, ENOMEM);
    212                 return;
    213         }
    214 
    215         /*
    216          * Fill argv with argument pointers
    217          */
    218         p = arg_buf;
    219         n = 0;
    220         while (p < arg_buf + buf_size) {
    221                 argv[n] = p;
    222                
    223                 arg_size = str_size(p);
    224                 p = p + arg_size + 1;
    225                 ++n;
    226         }
    227        
    228         argc = n;
    229         argv[n] = NULL;
    230 
    231         ipc_answer_0(rid, EOK);
     166        char *buf;
     167        size_t buf_size;
     168        int rc = async_data_write_accept((void **) &buf, true, 0, 0, 0, &buf_size);
     169       
     170        if (rc == EOK) {
     171                /*
     172                 * Count number of arguments
     173                 */
     174                char *cur = buf;
     175                int count = 0;
     176               
     177                while (cur < buf + buf_size) {
     178                        size_t arg_size = str_size(cur);
     179                        cur += arg_size + 1;
     180                        count++;
     181                }
     182               
     183                /*
     184                 * Allocate new argv
     185                 */
     186                char **_argv = (char **) malloc((count + 1) * sizeof(char *));
     187                if (_argv == NULL) {
     188                        free(buf);
     189                        async_answer_0(rid, ENOMEM);
     190                        return;
     191                }
     192               
     193                /*
     194                 * Fill the new argv with argument pointers
     195                 */
     196                cur = buf;
     197                count = 0;
     198                while (cur < buf + buf_size) {
     199                        _argv[count] = cur;
     200                       
     201                        size_t arg_size = str_size(cur);
     202                        cur += arg_size + 1;
     203                        count++;
     204                }
     205                _argv[count] = NULL;
     206               
     207                /*
     208                 * Copy temporary data to global variables
     209                 */
     210                if (arg_buf != NULL)
     211                        free(arg_buf);
     212               
     213                if (argv != NULL)
     214                        free(argv);
     215               
     216                argc = count;
     217                arg_buf = buf;
     218                argv = _argv;
     219        }
     220       
     221        async_answer_0(rid, rc);
    232222}
    233223
     
    239229static void ldr_set_files(ipc_callid_t rid, ipc_call_t *request)
    240230{
    241         ipc_callid_t callid;
     231        fdi_node_t *buf;
    242232        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);
     233        int rc = async_data_write_accept((void **) &buf, false, 0, 0,
     234            sizeof(fdi_node_t), &buf_size);
     235       
     236        if (rc == EOK) {
     237                int count = buf_size / sizeof(fdi_node_t);
     238               
     239                /*
     240                 * Allocate new filv
     241                 */
     242                fdi_node_t **_filv = (fdi_node_t **) calloc(count + 1, sizeof(fdi_node_t *));
     243                if (_filv == NULL) {
     244                        free(buf);
     245                        async_answer_0(rid, ENOMEM);
     246                        return;
     247                }
     248               
     249                /*
     250                 * Fill the new filv with argument pointers
     251                 */
     252                int i;
     253                for (i = 0; i < count; i++)
     254                        _filv[i] = &buf[i];
     255               
     256                _filv[count] = NULL;
     257               
     258                /*
     259                 * Copy temporary data to global variables
     260                 */
     261                if (fil_buf != NULL)
     262                        free(fil_buf);
     263               
     264                if (filv != NULL)
     265                        free(filv);
     266               
     267                filc = count;
     268                fil_buf = buf;
     269                filv = _filv;
     270        }
     271       
     272        async_answer_0(rid, EOK);
    296273}
    297274
     
    306283        int rc;
    307284       
    308         rc = elf_load_file(pathname, 0, 0, &prog_info);
     285        rc = elf_load_file(pathname, 0, &prog_info);
    309286        if (rc != EE_OK) {
    310287                DPRINTF("Failed to load executable '%s'.\n", pathname);
    311                 ipc_answer_0(rid, EINVAL);
     288                async_answer_0(rid, EINVAL);
    312289                return 1;
    313290        }
    314291       
    315292        elf_create_pcb(&prog_info, &pcb);
     293       
     294        pcb.cwd = cwd;
    316295       
    317296        pcb.argc = argc;
     
    324303                /* Statically linked program */
    325304                is_dyn_linked = false;
    326                 ipc_answer_0(rid, EOK);
     305                async_answer_0(rid, EOK);
    327306                return 0;
    328307        }
    329308       
    330         printf("Load ELF interpreter '%s'\n", prog_info.interp);
    331         rc = elf_load_file(prog_info.interp, 0, 0, &interp_info);
     309        rc = elf_load_file(prog_info.interp, 0, &interp_info);
    332310        if (rc != EE_OK) {
    333311                DPRINTF("Failed to load interpreter '%s.'\n",
    334312                    prog_info.interp);
    335                 ipc_answer_0(rid, EINVAL);
     313                async_answer_0(rid, EINVAL);
    336314                return 1;
    337315        }
    338316       
    339         printf("Run interpreter.\n");
    340         printf("entry point: 0x%lx\n", interp_info.entry);
    341         printf("pcb address: 0x%lx\n", &pcb);
    342         printf("prog dynamic: 0x%lx\n", prog_info.dynamic);
    343 
    344317        is_dyn_linked = true;
    345         ipc_answer_0(rid, EOK);
     318        async_answer_0(rid, EOK);
    346319       
    347320        return 0;
     
    367340                /* Dynamically linked program */
    368341                DPRINTF("Run ELF interpreter.\n");
    369                 DPRINTF("Entry point: 0x%lx\n", interp_info.entry);
    370                
    371                 ipc_answer_0(rid, EOK);
    372                 program_run(interp_info.entry, &pcb);
     342                DPRINTF("Entry point: %p\n", interp_info.entry);
     343               
     344                async_answer_0(rid, EOK);
     345                elf_run(&interp_info, &pcb);
    373346        } else {
    374347                /* Statically linked program */
    375                 ipc_answer_0(rid, EOK);
    376                 program_run(prog_info.entry, &pcb);
     348                async_answer_0(rid, EOK);
     349                elf_run(&prog_info, &pcb);
    377350        }
    378351       
     
    393366        /* Already have a connection? */
    394367        if (connected) {
    395                 ipc_answer_0(iid, ELIMIT);
     368                async_answer_0(iid, ELIMIT);
    396369                return;
    397370        }
     
    400373       
    401374        /* Accept the connection */
    402         ipc_answer_0(iid, EOK);
     375        async_answer_0(iid, EOK);
    403376       
    404377        /* Ignore parameters, the connection is already open */
     
    409382                callid = async_get_call(&call);
    410383               
    411                 switch (IPC_GET_METHOD(call)) {
     384                switch (IPC_GET_IMETHOD(call)) {
    412385                case IPC_M_PHONE_HUNGUP:
    413386                        exit(0);
    414387                case LOADER_GET_TASKID:
    415388                        ldr_get_taskid(callid, &call);
     389                        continue;
     390                case LOADER_SET_CWD:
     391                        ldr_set_cwd(callid, &call);
    416392                        continue;
    417393                case LOADER_SET_PATHNAME:
     
    434410                        break;
    435411                }
    436                 if ((callid & IPC_CALLID_NOTIFICATION) == 0 &&
    437                     IPC_GET_METHOD(call) != IPC_M_PHONE_HUNGUP) {
     412                if (IPC_GET_IMETHOD(call) != IPC_M_PHONE_HUNGUP) {
    438413                        DPRINTF("Responding EINVAL to method %d.\n",
    439                             IPC_GET_METHOD(call));
    440                         ipc_answer_0(callid, EINVAL);
     414                            IPC_GET_IMETHOD(call));
     415                        async_answer_0(callid, EINVAL);
    441416                }
    442417        }
     
    447422int main(int argc, char *argv[])
    448423{
    449         ipcarg_t phonead;
    450         task_id_t id;
    451         int rc;
    452 
    453         connected = false;
    454 
     424        /* Set a handler of incomming connections. */
     425        async_set_client_connection(ldr_connection);
     426       
    455427        /* 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));
     428        task_id_t id = task_get_id();
     429        int rc = async_req_2_0(PHONE_NS, NS_ID_INTRO, LOWER32(id), UPPER32(id));
    458430        if (rc != EOK)
    459431                return -1;
    460 
    461         /* Set a handler of incomming connections. */
    462         async_set_client_connection(ldr_connection);
    463432       
    464433        /* Register at naming service. */
    465         if (ipc_connect_to_me(PHONE_NS, SERVICE_LOAD, 0, 0, &phonead) != 0)
     434        if (service_register(SERVICE_LOAD) != EOK)
    466435                return -2;
    467 
     436       
    468437        async_manager();
    469438       
Note: See TracChangeset for help on using the changeset viewer.