Subversion Repositories HelenOS

Rev

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