Ignore:
File:
1 edited

Legend:

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

    rffa2c8ef r1ea99cc  
    5050#include <fcntl.h>
    5151#include <sys/types.h>
     52#include <ipc/ipc.h>
    5253#include <ipc/services.h>
    5354#include <ipc/loader.h>
     
    5758#include <errno.h>
    5859#include <async.h>
    59 #include <str.h>
     60#include <string.h>
    6061#include <as.h>
    6162
     
    6566#define DPRINTF(...)
    6667
     68void program_run(void *entry, pcb_t *pcb);
     69
    6770/** Pathname of the file that will be loaded */
    6871static char *pathname = NULL;
     
    7073/** The Program control block */
    7174static pcb_t pcb;
    72 
    73 /** Current working directory */
    74 static char *cwd = NULL;
    7575
    7676/** Number of arguments */
     
    9494
    9595/** Used to limit number of connections to one. */
    96 static bool connected = false;
     96static bool connected;
    9797
    9898static void ldr_get_taskid(ipc_callid_t rid, ipc_call_t *request)
     
    104104        task_id = task_get_id();
    105105       
    106         if (!async_data_read_receive(&callid, &len)) {
    107                 async_answer_0(callid, EINVAL);
    108                 async_answer_0(rid, EINVAL);
     106        if (!ipc_data_read_receive(&callid, &len)) {
     107                ipc_answer_0(callid, EINVAL);
     108                ipc_answer_0(rid, EINVAL);
    109109                return;
    110110        }
     
    113113                len = sizeof(task_id);
    114114       
    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.
     115        ipc_data_read_finalize(callid, &task_id, len);
     116        ipc_answer_0(rid, EOK);
     117}
     118
     119
     120/** Receive a call setting pathname of the program to execute.
    120121 *
    121122 * @param rid
    122123 * @param request
    123124 */
    124 static 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 }
    138 
    139 /** Receive a call setting pathname of the program to execute.
     125static void ldr_set_pathname(ipc_callid_t rid, ipc_call_t *request)
     126{
     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;
     154}
     155
     156/** Receive a call setting arguments of the program to execute.
    140157 *
    141158 * @param rid
    142159 * @param request
    143160 */
    144 static void ldr_set_pathname(ipc_callid_t rid, ipc_call_t *request)
    145 {
    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);
     161static void ldr_set_args(ipc_callid_t rid, ipc_call_t *request)
     162{
     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;
    152222               
    153                 pathname = buf;
    154         }
    155        
    156         async_answer_0(rid, rc);
    157 }
    158 
    159 /** Receive a call setting arguments of the program to execute.
     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);
     232}
     233
     234/** Receive a call setting preset files of the program to execute.
    160235 *
    161236 * @param rid
    162237 * @param request
    163238 */
    164 static void ldr_set_args(ipc_callid_t rid, ipc_call_t *request)
    165 {
    166         char *buf;
     239static void ldr_set_files(ipc_callid_t rid, ipc_call_t *request)
     240{
     241        ipc_callid_t callid;
    167242        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);
    222 }
    223 
    224 /** Receive a call setting preset files of the program to execute.
    225  *
    226  * @param rid
    227  * @param request
    228  */
    229 static void ldr_set_files(ipc_callid_t rid, ipc_call_t *request)
    230 {
    231         fdi_node_t *buf;
    232         size_t buf_size;
    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);
     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);
    273296}
    274297
     
    283306        int rc;
    284307       
    285         rc = elf_load_file(pathname, 0, &prog_info);
     308        rc = elf_load_file(pathname, 0, 0, &prog_info);
    286309        if (rc != EE_OK) {
    287310                DPRINTF("Failed to load executable '%s'.\n", pathname);
    288                 async_answer_0(rid, EINVAL);
     311                ipc_answer_0(rid, EINVAL);
    289312                return 1;
    290313        }
    291314       
    292315        elf_create_pcb(&prog_info, &pcb);
    293        
    294         pcb.cwd = cwd;
    295316       
    296317        pcb.argc = argc;
     
    303324                /* Statically linked program */
    304325                is_dyn_linked = false;
    305                 async_answer_0(rid, EOK);
     326                ipc_answer_0(rid, EOK);
    306327                return 0;
    307328        }
    308329       
    309         rc = elf_load_file(prog_info.interp, 0, &interp_info);
     330        printf("Load ELF interpreter '%s'\n", prog_info.interp);
     331        rc = elf_load_file(prog_info.interp, 0, 0, &interp_info);
    310332        if (rc != EE_OK) {
    311333                DPRINTF("Failed to load interpreter '%s.'\n",
    312334                    prog_info.interp);
    313                 async_answer_0(rid, EINVAL);
     335                ipc_answer_0(rid, EINVAL);
    314336                return 1;
    315337        }
    316338       
     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
    317344        is_dyn_linked = true;
    318         async_answer_0(rid, EOK);
     345        ipc_answer_0(rid, EOK);
    319346       
    320347        return 0;
     
    340367                /* Dynamically linked program */
    341368                DPRINTF("Run ELF interpreter.\n");
    342                 DPRINTF("Entry point: %p\n", interp_info.entry);
     369                DPRINTF("Entry point: 0x%lx\n", interp_info.entry);
    343370               
    344                 async_answer_0(rid, EOK);
    345                 elf_run(&interp_info, &pcb);
     371                ipc_answer_0(rid, EOK);
     372                program_run(interp_info.entry, &pcb);
    346373        } else {
    347374                /* Statically linked program */
    348                 async_answer_0(rid, EOK);
    349                 elf_run(&prog_info, &pcb);
     375                ipc_answer_0(rid, EOK);
     376                program_run(prog_info.entry, &pcb);
    350377        }
    351378       
     
    366393        /* Already have a connection? */
    367394        if (connected) {
    368                 async_answer_0(iid, ELIMIT);
     395                ipc_answer_0(iid, ELIMIT);
    369396                return;
    370397        }
     
    373400       
    374401        /* Accept the connection */
    375         async_answer_0(iid, EOK);
     402        ipc_answer_0(iid, EOK);
    376403       
    377404        /* Ignore parameters, the connection is already open */
     
    382409                callid = async_get_call(&call);
    383410               
    384                 switch (IPC_GET_IMETHOD(call)) {
     411                switch (IPC_GET_METHOD(call)) {
    385412                case IPC_M_PHONE_HUNGUP:
    386413                        exit(0);
    387414                case LOADER_GET_TASKID:
    388415                        ldr_get_taskid(callid, &call);
    389                         continue;
    390                 case LOADER_SET_CWD:
    391                         ldr_set_cwd(callid, &call);
    392416                        continue;
    393417                case LOADER_SET_PATHNAME:
     
    410434                        break;
    411435                }
    412                 if (IPC_GET_IMETHOD(call) != IPC_M_PHONE_HUNGUP) {
     436                if ((callid & IPC_CALLID_NOTIFICATION) == 0 &&
     437                    IPC_GET_METHOD(call) != IPC_M_PHONE_HUNGUP) {
    413438                        DPRINTF("Responding EINVAL to method %d.\n",
    414                             IPC_GET_IMETHOD(call));
    415                         async_answer_0(callid, EINVAL);
     439                            IPC_GET_METHOD(call));
     440                        ipc_answer_0(callid, EINVAL);
    416441                }
    417442        }
     
    422447int main(int argc, char *argv[])
    423448{
     449        ipcarg_t phonead;
     450        task_id_t id;
     451        int rc;
     452
     453        connected = false;
     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
    424461        /* Set a handler of incomming connections. */
    425462        async_set_client_connection(ldr_connection);
    426463       
    427         /* Introduce this task to the NS (give it our task 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));
    430         if (rc != EOK)
    431                 return -1;
    432        
    433464        /* Register at naming service. */
    434         if (service_register(SERVICE_LOAD) != EOK)
     465        if (ipc_connect_to_me(PHONE_NS, SERVICE_LOAD, 0, 0, &phonead) != 0)
    435466                return -2;
    436        
     467
    437468        async_manager();
    438469       
Note: See TracChangeset for help on using the changeset viewer.