Subversion Repositories HelenOS

Rev

Rev 3470 | Rev 3536 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. /*
  2.  * Copyright (c) 2008 Jiri Svoboda
  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.  *
  9.  * - Redistributions of source code must retain the above copyright
  10.  *   notice, this list of conditions and the following disclaimer.
  11.  * - Redistributions in binary form must reproduce the above copyright
  12.  *   notice, this list of conditions and the following disclaimer in the
  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
  15.  *   derived from this software without specific prior written permission.
  16.  *
  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
  19.  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  20.  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
  21.  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  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
  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
  26.  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  27.  */
  28.  
  29. /** @addtogroup libc
  30.  * @{
  31.  */
  32. /** @file
  33.  */
  34.  
  35. #include <ipc/ipc.h>
  36. #include <ipc/loader.h>
  37. #include <libc.h>
  38. #include <string.h>
  39. #include <stdlib.h>
  40. #include <async.h>
  41. #include <errno.h>
  42. #include <vfs/vfs.h>
  43. #include <loader/loader.h>
  44.  
  45. /** Connect to a new program loader.
  46.  *
  47.  * Spawns a new program loader task and returns the connection structure.
  48.  * @return  Pointer to the loader connection structure (should be
  49.  *      de-allocated using free() after use).
  50.  */
  51. loader_t *loader_spawn(void)
  52. {
  53.     int phone_id, rc;
  54.     loader_t *ldr;
  55.  
  56.     /*
  57.      * Ask kernel to spawn a new loader task.
  58.      */
  59.     rc = __SYSCALL1(SYS_PROGRAM_SPAWN_LOADER, (sysarg_t) &phone_id);
  60.     if (rc != 0)
  61.         return NULL;
  62.  
  63.     /*
  64.      * Say hello so that the loader knows the incoming connection's
  65.      * phone hash.
  66.      */
  67.     rc = async_req_0_0(phone_id, LOADER_HELLO);
  68.     if (rc != EOK)
  69.         return NULL;
  70.  
  71.     ldr = malloc(sizeof(loader_t));
  72.     if (ldr == NULL)
  73.         return NULL;
  74.  
  75.     ldr->phone_id = phone_id;
  76.     return ldr;
  77. }
  78.  
  79. /** Get ID of the new task.
  80.  *
  81.  * Retrieves the ID of the new task from the loader.
  82.  *
  83.  * @param ldr       Loader connection structure.
  84.  * @param task_id   Points to a variable where the ID should be stored.
  85.  * @return      Zero on success or negative error code.
  86.  */
  87. int loader_get_task_id(loader_t *ldr, task_id_t *task_id)
  88. {
  89.     ipc_call_t answer;
  90.     aid_t req;
  91.     int rc;
  92.     ipcarg_t retval;
  93.  
  94.     /* Get task ID. */
  95.     req = async_send_0(ldr->phone_id, LOADER_GET_TASKID, &answer);
  96.     rc = ipc_data_read_start(ldr->phone_id, task_id, sizeof(task_id));
  97.     if (rc != EOK) {
  98.         async_wait_for(req, NULL);
  99.         return rc;
  100.     }
  101.  
  102.     async_wait_for(req, &retval);
  103.     return (int)retval;
  104. }
  105.  
  106. /** Set pathname of the program to load.
  107.  *
  108.  * Sets the name of the program file to load. The name can be relative
  109.  * to the current working directory (it will be absolutized before
  110.  * sending to the loader).
  111.  *
  112.  * @param ldr       Loader connection structure.
  113.  * @param path      Pathname of the program file.
  114.  * @return      Zero on success or negative error code.
  115.  */
  116. int loader_set_pathname(loader_t *ldr, const char *path)
  117. {
  118.     ipc_call_t answer;
  119.     aid_t req;
  120.     int rc;
  121.     ipcarg_t retval;
  122.  
  123.     char *pa;
  124.     size_t pa_len;
  125.  
  126.     pa = absolutize(path, &pa_len);
  127.     if (!pa)
  128.         return 0;
  129.  
  130.     /* Send program pathname */
  131.     req = async_send_0(ldr->phone_id, LOADER_SET_PATHNAME, &answer);
  132.     rc = ipc_data_write_start(ldr->phone_id, (void *)pa, pa_len);
  133.     if (rc != EOK) {
  134.         async_wait_for(req, NULL);
  135.         return rc;
  136.     }
  137.  
  138.     free(pa);
  139.  
  140.     async_wait_for(req, &retval);
  141.     return (int)retval;
  142. }
  143.  
  144.  
  145. /** Set command-line arguments for the program.
  146.  *
  147.  * Sets the vector of command-line arguments to be passed to the loaded
  148.  * program. By convention, the very first argument is typically the same as
  149.  * the command used to execute the program.
  150.  *
  151.  * @param ldr       Loader connection structure.
  152.  * @param argv      NULL-terminated array of pointers to arguments.
  153.  * @return      Zero on success or negative error code.
  154.  */
  155. int loader_set_args(loader_t *ldr, char *const argv[])
  156. {
  157.     aid_t req;
  158.     ipc_call_t answer;
  159.     ipcarg_t rc;
  160.  
  161.     char *const *ap;
  162.     char *dp;
  163.     char *arg_buf;
  164.     size_t buffer_size;
  165.  
  166.     /*
  167.      * Serialize the arguments into a single array. First
  168.      * compute size of the buffer needed.
  169.      */
  170.     ap = argv;
  171.     buffer_size = 0;
  172.     while (*ap != NULL) {
  173.         buffer_size += strlen(*ap) + 1;
  174.         ++ap;
  175.     }
  176.  
  177.     arg_buf = malloc(buffer_size);
  178.     if (arg_buf == NULL) return ENOMEM;
  179.  
  180.     /* Now fill the buffer with null-terminated argument strings */
  181.     ap = argv;
  182.     dp = arg_buf;
  183.     while (*ap != NULL) {
  184.         strcpy(dp, *ap);
  185.         dp += strlen(*ap) + 1;
  186.  
  187.         ++ap;
  188.     }
  189.  
  190.     /* Send serialized arguments to the loader */
  191.  
  192.     req = async_send_0(ldr->phone_id, LOADER_SET_ARGS, &answer);
  193.     rc = ipc_data_write_start(ldr->phone_id, (void *)arg_buf, buffer_size);
  194.     if (rc != EOK) {
  195.         async_wait_for(req, NULL);
  196.         return rc;
  197.     }
  198.  
  199.     async_wait_for(req, &rc);
  200.     if (rc != EOK) return rc;
  201.  
  202.     /* Free temporary buffer */
  203.     free(arg_buf);
  204.  
  205.     return EOK;
  206. }
  207.  
  208. /** Instruct loader to load the program.
  209.  *
  210.  * If this function succeeds, the program has been successfully loaded
  211.  * and is ready to be executed.
  212.  *
  213.  * @param ldr       Loader connection structure.
  214.  * @return      Zero on success or negative error code.
  215.  */
  216. int loader_load_program(loader_t *ldr)
  217. {
  218.     int rc;
  219.  
  220.     rc = async_req_0_0(ldr->phone_id, LOADER_LOAD);
  221.     if (rc != EOK)
  222.         return rc;
  223.  
  224.     return EOK;
  225. }
  226.  
  227. /** Instruct loader to execute the program.
  228.  *
  229.  * Note that this function blocks until the loader actually replies
  230.  * so you cannot expect this function to return if you are debugging
  231.  * the task and its thread is stopped.
  232.  *
  233.  * After using this function, no further operations must be performed
  234.  * on the loader structure. It should be de-allocated using free().
  235.  *
  236.  * @param ldr       Loader connection structure.
  237.  * @return      Zero on success or negative error code.
  238.  */
  239. int loader_run(loader_t *ldr)
  240. {
  241.     int rc;
  242.  
  243.     rc = async_req_0_0(ldr->phone_id, LOADER_RUN);
  244.     if (rc != EOK)
  245.         return rc;
  246.  
  247.     return EOK;
  248. }
  249.  
  250. /** Cancel the loader session.
  251.  *
  252.  * Tells the loader not to load any program and terminate.
  253.  * After using this function, no further operations must be performed
  254.  * on the loader structure. It should be de-allocated using free().
  255.  *
  256.  * @param ldr       Loader connection structure.
  257.  * @return      Zero on success or negative error code.
  258.  */
  259. void loader_abort(loader_t *ldr)
  260. {
  261.     ipc_hangup(ldr->phone_id);
  262.     ldr->phone_id = 0;
  263. }
  264.  
  265. /** @}
  266.  */
  267.