Rev 3386 | Rev 4263 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
| Rev 3386 | Rev 4153 | ||
|---|---|---|---|
| Line 65... | Line 65... | ||
| 65 | 65 | ||
| 66 | /** Create a program using an existing address space. |
66 | /** Create a program using an existing address space. |
| 67 | * |
67 | * |
| 68 | * @param as Address space containing a binary program image. |
68 | * @param as Address space containing a binary program image. |
| 69 | * @param entry_addr Program entry-point address in program address space. |
69 | * @param entry_addr Program entry-point address in program address space. |
| - | 70 | * @param name Name to set for the program's task. |
|
| 70 | * @param p Buffer for storing program information. |
71 | * @param p Buffer for storing program information. |
| 71 | */ |
72 | */ |
| 72 | void program_create(as_t *as, uintptr_t entry_addr, program_t *p) |
73 | void program_create(as_t *as, uintptr_t entry_addr, char *name, program_t *p) |
| 73 | { |
74 | { |
| 74 | as_area_t *a; |
75 | as_area_t *a; |
| 75 | uspace_arg_t *kernel_uarg; |
76 | uspace_arg_t *kernel_uarg; |
| 76 | 77 | ||
| 77 | kernel_uarg = (uspace_arg_t *) malloc(sizeof(uspace_arg_t), 0); |
78 | kernel_uarg = (uspace_arg_t *) malloc(sizeof(uspace_arg_t), 0); |
| Line 79... | Line 80... | ||
| 79 | kernel_uarg->uspace_stack = (void *) USTACK_ADDRESS; |
80 | kernel_uarg->uspace_stack = (void *) USTACK_ADDRESS; |
| 80 | kernel_uarg->uspace_thread_function = NULL; |
81 | kernel_uarg->uspace_thread_function = NULL; |
| 81 | kernel_uarg->uspace_thread_arg = NULL; |
82 | kernel_uarg->uspace_thread_arg = NULL; |
| 82 | kernel_uarg->uspace_uarg = NULL; |
83 | kernel_uarg->uspace_uarg = NULL; |
| 83 | 84 | ||
| 84 | p->task = task_create(as, "app"); |
85 | p->task = task_create(as, name); |
| 85 | ASSERT(p->task); |
86 | ASSERT(p->task); |
| 86 | 87 | ||
| 87 | /* |
88 | /* |
| 88 | * Create the data as_area. |
89 | * Create the data as_area. |
| 89 | */ |
90 | */ |
| Line 104... | Line 105... | ||
| 104 | * If the image belongs to a program loader, it is registered as such, |
105 | * If the image belongs to a program loader, it is registered as such, |
| 105 | * (and *task is set to NULL). Otherwise a task is created from the |
106 | * (and *task is set to NULL). Otherwise a task is created from the |
| 106 | * executable image. The task is returned in *task. |
107 | * executable image. The task is returned in *task. |
| 107 | * |
108 | * |
| 108 | * @param image_addr Address of an executable program image. |
109 | * @param image_addr Address of an executable program image. |
| - | 110 | * @param name Name to set for the program's task. |
|
| 109 | * @param p Buffer for storing program info. If image_addr |
111 | * @param p Buffer for storing program info. If image_addr |
| 110 | * points to a loader image, p->task will be set to |
112 | * points to a loader image, p->task will be set to |
| 111 | * NULL and EOK will be returned. |
113 | * NULL and EOK will be returned. |
| 112 | * |
114 | * |
| 113 | * @return EOK on success or negative error code. |
115 | * @return EOK on success or negative error code. |
| 114 | */ |
116 | */ |
| 115 | int program_create_from_image(void *image_addr, program_t *p) |
117 | int program_create_from_image(void *image_addr, char *name, program_t *p) |
| 116 | { |
118 | { |
| 117 | as_t *as; |
119 | as_t *as; |
| 118 | unsigned int rc; |
120 | unsigned int rc; |
| 119 | 121 | ||
| 120 | as = as_create(0); |
122 | as = as_create(0); |
| Line 134... | Line 136... | ||
| 134 | printf("Registered program loader at 0x%" PRIp "\n", |
136 | printf("Registered program loader at 0x%" PRIp "\n", |
| 135 | image_addr); |
137 | image_addr); |
| 136 | return EOK; |
138 | return EOK; |
| 137 | } |
139 | } |
| 138 | 140 | ||
| 139 | program_create(as, ((elf_header_t *) image_addr)->e_entry, p); |
141 | program_create(as, ((elf_header_t *) image_addr)->e_entry, name, p); |
| 140 | 142 | ||
| 141 | return EOK; |
143 | return EOK; |
| 142 | } |
144 | } |
| 143 | 145 | ||
| 144 | /** Create a task from the program loader image. |
146 | /** Create a task from the program loader image. |
| 145 | * |
147 | * |
| 146 | * @param p Buffer for storing program info. |
148 | * @param p Buffer for storing program info. |
| - | 149 | * @param name Name to set for the program's task. |
|
| - | 150 | * |
|
| 147 | * @return EOK on success or negative error code. |
151 | * @return EOK on success or negative error code. |
| 148 | */ |
152 | */ |
| 149 | int program_create_loader(program_t *p) |
153 | int program_create_loader(program_t *p, char *name) |
| 150 | { |
154 | { |
| 151 | as_t *as; |
155 | as_t *as; |
| 152 | unsigned int rc; |
156 | unsigned int rc; |
| 153 | void *loader; |
157 | void *loader; |
| 154 | 158 | ||
| Line 165... | Line 169... | ||
| 165 | if (rc != EE_OK) { |
169 | if (rc != EE_OK) { |
| 166 | as_destroy(as); |
170 | as_destroy(as); |
| 167 | return ENOENT; |
171 | return ENOENT; |
| 168 | } |
172 | } |
| 169 | 173 | ||
| 170 | program_create(as, ((elf_header_t *) program_loader)->e_entry, p); |
174 | program_create(as, ((elf_header_t *) program_loader)->e_entry, |
| - | 175 | name, p); |
|
| 171 | 176 | ||
| 172 | return EOK; |
177 | return EOK; |
| 173 | } |
178 | } |
| 174 | 179 | ||
| 175 | /** Make program ready. |
180 | /** Make program ready. |
| Line 183... | Line 188... | ||
| 183 | thread_ready(p->main_thread); |
188 | thread_ready(p->main_thread); |
| 184 | } |
189 | } |
| 185 | 190 | ||
| 186 | /** Syscall for creating a new loader instance from userspace. |
191 | /** Syscall for creating a new loader instance from userspace. |
| 187 | * |
192 | * |
| 188 | * Creates a new task from the program loader image, connects a phone |
193 | * Creates a new task from the program loader image and sets |
| 189 | * to it and stores the phone id into the provided buffer. |
194 | * the task name. |
| 190 | * |
195 | * |
| 191 | * @param uspace_phone_id Userspace address where to store the phone id. |
196 | * @param name Name to set on the new task (typically the same |
| - | 197 | * as the command used to execute it). |
|
| 192 | * |
198 | * |
| 193 | * @return 0 on success or an error code from @ref errno.h. |
199 | * @return 0 on success or an error code from @ref errno.h. |
| 194 | */ |
200 | */ |
| 195 | unative_t sys_program_spawn_loader(int *uspace_phone_id) |
201 | unative_t sys_program_spawn_loader(char *uspace_name, size_t name_len) |
| 196 | { |
202 | { |
| 197 | program_t p; |
203 | program_t p; |
| 198 | int fake_id; |
- | |
| 199 | int rc; |
204 | int rc; |
| 200 | int phone_id; |
- | |
| 201 | - | ||
| 202 | fake_id = 0; |
205 | char namebuf[TASK_NAME_BUFLEN]; |
| 203 | 206 | ||
| 204 | /* Before we even try creating the task, see if we can write the id */ |
207 | /* Cap length of name and copy it from userspace. */ |
| 205 | rc = (unative_t) copy_to_uspace(uspace_phone_id, &fake_id, |
- | |
| 206 | sizeof(fake_id)); |
- | |
| 207 | if (rc != 0) |
- | |
| 208 | return rc; |
- | |
| 209 | 208 | ||
| 210 | phone_id = phone_alloc(); |
209 | if (name_len > TASK_NAME_BUFLEN - 1) |
| 211 | if (phone_id < 0) |
- | |
| 212 | return ELIMIT; |
210 | name_len = TASK_NAME_BUFLEN - 1; |
| 213 | 211 | ||
| 214 | rc = program_create_loader(&p); |
212 | rc = copy_from_uspace(namebuf, uspace_name, name_len); |
| 215 | if (rc != 0) |
213 | if (rc != 0) |
| 216 | return rc; |
214 | return (unative_t) rc; |
| - | 215 | ||
| - | 216 | namebuf[name_len] = '\0'; |
|
| 217 | 217 | ||
| 218 | phone_connect(phone_id, &p.task->answerbox); |
218 | /* Spawn the new task. */ |
| 219 | 219 | ||
| 220 | /* No need to aquire lock before task_ready() */ |
220 | rc = program_create_loader(&p, namebuf); |
| 221 | rc = (unative_t) copy_to_uspace(uspace_phone_id, &phone_id, |
- | |
| 222 | sizeof(phone_id)); |
- | |
| 223 | if (rc != 0) { |
221 | if (rc != 0) |
| 224 | /* Ooops */ |
- | |
| 225 | ipc_phone_hangup(&TASK->phones[phone_id]); |
- | |
| 226 | task_kill(p.task->taskid); |
- | |
| 227 | return rc; |
222 | return rc; |
| 228 | } |
- | |
| 229 | 223 | ||
| 230 | // FIXME: control the capabilities |
224 | // FIXME: control the capabilities |
| 231 | cap_set(p.task, cap_get(TASK)); |
225 | cap_set(p.task, cap_get(TASK)); |
| 232 | 226 | ||
| 233 | program_ready(&p); |
227 | program_ready(&p); |