tlk: 6/19 update
[3rdparty/ote_partner/tlk.git] / kernel / task_load.c
1 /*
2  * Copyright (c) 2013-2014, NVIDIA CORPORATION. All rights reserved
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining
5  * a copy of this software and associated documentation files
6  * (the "Software"), to deal in the Software without restriction,
7  * including without limitation the rights to use, copy, modify, merge,
8  * publish, distribute, sublicense, and/or sell copies of the Software,
9  * and to permit persons to whom the Software is furnished to do so,
10  * subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice shall be
13  * included in all copies or substantial portions of the Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
19  * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
20  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
21  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22  */
23 #include <debug.h>
24 #include <sys/types.h>
25 #include <assert.h>
26 #include <string.h>
27 #include <malloc.h>
28 #include <err.h>
29 #include <errno.h>
30 #include <stdlib.h>
31 #include <kernel/task.h>
32 #include <kernel/thread.h>
33 #include <kernel/task_load.h>
34 #include <lib/heap.h>
35
36 /* for handling requests from syscall.c */
37 #include <lib/ote/ote_protocol.h>
38
39 #ifndef TASK_HEAP_PERCENTAGE
40 /*
41  * Max 60% of heap can be used for task loading.
42  * Define as 0 to disable task loading.
43  */
44 #define TASK_HEAP_PERCENTAGE 60
45 #endif /* TASK_HEAP_PERCENTAGE */
46
47 #ifndef TASK_HEAP_PAGES_RESERVED
48 /*
49  * Task loading will leave this many pages for TLK heap use
50  * no matter what the percentage above is or no matter what
51  * the heap size is.
52  *
53  * If the heap is too small, task loading will be disabled.
54  */
55 #define TASK_HEAP_PAGES_RESERVED 50
56 #endif /* TASK_HEAP_PAGES_RESERVED */
57
58 #ifndef TASK_HEAP_PAGES_MIN
59 /*
60  * No point in supporting task loading if there are less pages
61  * than this to load tasks to.
62  *
63  * If the heap is too small, task loading will be disabled.
64  */
65 #define TASK_HEAP_PAGES_MIN     20
66 #endif /* TASK_HEAP_PAGES_MIN */
67
68 /* Pending task-load states (before task is fully loaded)
69  *
70  * The tp_state_t defines the internal states of the state machine used
71  * for the multi-step task loading operation. Once completed or on error
72  * the associated task_pending_t node will be deleted and the task be
73  * either installed or rejected.
74  */
75 typedef enum {
76         TASK_PSTATE_UNDEFINED,   /* uninitialized */
77         TASK_PSTATE_INVALID,     /* allocated, undefined */
78         TASK_PSTATE_MEMBUF,      /* memory allocated for task */
79         TASK_PSTATE_TA_MAPPED,   /* shared buffer mapped for copying task image */
80         TASK_PSTATE_TA_UNMAPPED, /* shared buffer unmapped; task image copied */
81         TASK_PSTATE_PREPARED,    /* task parsed */
82         TASK_PSTATE_READY        /* task started (pending node deallocated) */
83 } tp_state_t;
84
85 /*
86  * Each task loading operation will get a pending node associated with it.
87  * The node exists only during the load process.
88  *
89  * Completed/rejected task installs are removed from this list and the pending node
90  * gets deleted.
91  */
92 typedef struct {
93         uint32_t        tp_handle;
94         tp_state_t      tp_state;
95         task_t          tp_task;
96         vaddr_t         tp_task_tlk_addr;       /* task virt address in TLK */
97         uint32_t        tp_task_size;
98         vaddr_t         tp_task_ta_addr;        /* task virt address in TA */
99         struct list_node tp_node;
100 } task_pending_t;
101
102 static struct list_node task_pending_list;
103
104 /*
105  * Count task pages allocated and max number of pages allowed
106  * for task loading.
107  *
108  * TASK_HEAP_PERCENTAGE defines how much of the total TLK heap can
109  * be used for this.
110  */
111 static u_int task_pages_heap_used;
112 static u_int task_pages_heap_max;
113 static u_int task_heap_percentage = TASK_HEAP_PERCENTAGE;
114
115 static vaddr_t original_heap_start;
116 static vaddr_t original_heap_end;
117
118 static uint32_t task_load_counter;
119
120 void task_load_config(vaddr_t vaddr_begin, vaddr_t *vaddr_end_p)
121 {
122         u_int heap_pages = 0;
123
124         /* if no memory available, just return */
125         if (!vaddr_end_p || *vaddr_end_p == 0)
126                 goto exit;
127
128         /* save the original limit values for info (heap begin..end) */
129         original_heap_start = vaddr_begin;
130         original_heap_end   = *vaddr_end_p;
131
132         if ((original_heap_start == 0) ||
133             (original_heap_start >= original_heap_end) ||
134             (task_heap_percentage == 0))
135                 goto exit;
136
137         heap_pages = (original_heap_end - original_heap_start) / PAGE_SIZE;
138
139         if (heap_pages <= TASK_HEAP_PAGES_RESERVED) {
140                 dprintf(INFO, "heap too small for task loading (%d pages)\n",
141                         heap_pages);
142                 goto exit;
143         }
144
145         /*
146          * Max number of heap pages allowed for task loading
147          * This is an upper limit, less heap may be available at runtime.
148          */
149         task_pages_heap_max =
150                 (heap_pages / 100) * task_heap_percentage;
151
152         if (heap_pages - task_pages_heap_max < TASK_HEAP_PAGES_RESERVED)
153                 task_pages_heap_max = heap_pages - TASK_HEAP_PAGES_RESERVED;
154
155         if (task_pages_heap_max < TASK_HEAP_PAGES_MIN) {
156                 dprintf(INFO, "Not enough pages for task loading (%d pages)\n",
157                         task_pages_heap_max);
158
159                 task_pages_heap_max = 0;
160                 goto exit;
161         }
162
163         dprintf(INFO, "Max heap %d pages; task load limit %d pages\n",
164                 heap_pages, task_pages_heap_max);
165
166         if (0) {
167         exit:
168                 dprintf(INFO, "task loading not supported\n");
169         }
170 }
171
172 void task_load_init()
173 {
174         list_initialize(&task_pending_list);
175 }
176
177 u_int task_allowed_to_load_tasks(task_t *taskp)
178 {
179         return (taskp && (taskp->props.authorizations & OTE_AUTHORIZE_INSTALL));
180 }
181
182 static void task_add_new_pending(task_pending_t *tp, vaddr_t addr, uint32_t size,
183                                  tp_state_t pstate)
184 {
185         uint32_t handle = 0;
186         int found = 0;
187
188         if (!tp || !size || !addr)
189                 return;
190
191         tp->tp_task_tlk_addr = addr;    /* task address in TLK */
192         tp->tp_task_ta_addr = 0;        /* TA address not yet mapped */
193         tp->tp_task_size = size;        /* task byte size */
194         tp->tp_state = TASK_PSTATE_INVALID;
195
196         do {
197                 task_pending_t *tp_scan = NULL;
198
199                 found = 0;
200
201                 handle = platform_get_rand32(); /* need to push a unique non-zero handle */
202                 if (!handle)
203                         handle++;               /* zero means handle unused */
204
205                 enter_critical_section();
206
207                 list_for_every_entry(&task_pending_list, tp_scan,
208                                      task_pending_t, tp_node) {
209                         if (tp_scan->tp_handle == handle) {
210                                 found++;
211                                 break;
212                         }
213                 }
214
215                 /* new handle found; reserve it */
216                 if (!found) {
217                         tp->tp_handle = handle;
218                         tp->tp_state  = pstate;
219                         list_add_tail(&task_pending_list, &tp->tp_node);
220                 }
221                 exit_critical_section();
222
223         } while (found);
224 }
225
226 /*
227  * Atomically search pending task by random handle
228  * Found entry is removed from the list so caller must push it back if required.
229  */
230 static task_pending_t *task_find_pending(uint32_t handle)
231 {
232         task_pending_t *tp_scan = NULL;
233         int found = 0;
234
235         enter_critical_section();
236
237         list_for_every_entry(&task_pending_list, tp_scan, task_pending_t, tp_node) {
238                 if (tp_scan->tp_handle == handle) {
239                         found++;
240
241                         list_delete(&tp_scan->tp_node);
242                         break;
243                 }
244         }
245
246         exit_critical_section();
247
248         if (!found)
249                 tp_scan = NULL;
250
251         return tp_scan;
252 }
253
254 static void task_push_pending(task_pending_t *tp, tp_state_t pstate)
255 {
256         if (tp) {
257                 tp->tp_state = pstate;
258
259                 enter_critical_section();
260                 list_add_tail(&task_pending_list, &tp->tp_node);
261                 exit_critical_section();
262         }
263 }
264
265 /*
266  * Map the reserved memory virtual address into the target TA
267  * task address space.
268  */
269 static status_t task_map_memory_to_ta(task_t *taskp, uint32_t handle,
270                                       vaddr_t *ta_addr_p)
271 {
272         status_t err = NO_ERROR;
273         int flags = TM_UW | TM_UR | TM_KERN_SEC_VA;
274         task_map_t *mptr = NULL;
275         task_pending_t *tp  = NULL;
276
277         if (!taskp || !ta_addr_p)
278                 return ERR_INVALID_ARGS;
279
280         tp = task_find_pending(handle);
281         if (!tp) {
282                 dprintf(SPEW, "%s: task handle unknown 0x%x\n",
283                         __func__, handle);
284                 err = ERR_NOT_FOUND;
285                 goto exit;
286         }
287
288         if (tp->tp_state != TASK_PSTATE_MEMBUF) {
289                 dprintf(CRITICAL, "%s: task handle 0x%x in wrong state: %d\n",
290                         __func__, handle, tp->tp_state);
291                 err = ERR_TASK_GENERIC;
292                 goto exit;
293         }
294
295         mptr = arch_task_map_memory(taskp, tp->tp_task_tlk_addr,
296                                     tp->tp_task_size, flags);
297         if (mptr == NULL) {
298                 dprintf(CRITICAL, "TLK vaddr app load memory map failed for 0x%lx (%d bytes))\n",
299                         (unsigned long)tp->tp_task_tlk_addr, tp->tp_task_size);
300                 err = ERR_NO_MEMORY;
301                 goto exit;
302         }
303
304         tp->tp_task_ta_addr = mptr->vaddr;
305         *ta_addr_p = mptr->vaddr;
306
307         task_push_pending(tp, TASK_PSTATE_TA_MAPPED);
308
309         if (0) {
310         exit:
311                 /* released by caller */
312                 if (tp)
313                         task_push_pending(tp, TASK_PSTATE_INVALID);
314
315                 if (err == NO_ERROR)
316                         err = ERR_GENERIC;
317         }
318
319         return err;
320 }
321
322 /* @brief Task loading step#1/3, request TLK shared memory mapping to TA space
323  *
324  * Allocate page aligned memory from the TLK heap for app loading and
325  * map it to TA memory. TA then copies the TASK into this memory area
326  * and calls tlk_handle_app_prepare.
327  */
328 status_t task_request_app_load_memory(u_int byte_size, uint32_t *handle_p)
329 {
330         status_t err = NO_ERROR;
331         u_int    npages = 0;
332         vaddr_t  load_addr = NULL;
333         task_pending_t *tp = NULL;
334
335         if (byte_size <= 0 || !handle_p) {
336                 err = ERR_INVALID_ARGS;
337                 goto exit;
338         }
339
340         *handle_p = 0;
341         npages = ROUNDUP(byte_size, PAGE_SIZE) / PAGE_SIZE;
342
343         dprintf(SPEW, "TASK MEM ALLOCATION REQUEST => %d bytes (rounded to %d pages)\n",
344                 byte_size, npages);
345
346         load_addr = (vaddr_t)heap_alloc((npages * PAGE_SIZE), PAGE_SIZE);
347         if (!load_addr) {
348                 err = ERR_NO_MEMORY;
349                 goto exit;
350         }
351         memset((void *)load_addr, 0, npages * PAGE_SIZE);
352
353         tp = malloc(sizeof(task_pending_t));
354         if (!tp) {
355                 err = ERR_NO_MEMORY;
356                 goto exit;
357         }
358         memset(tp, 0, sizeof(task_pending_t));
359
360         /* check for an upper limit for heap allocation for task loading */
361         enter_critical_section();
362
363         if (task_pages_heap_used + npages > task_pages_heap_max) {
364                 err = ERR_TASK_GENERIC;
365         } else {
366                 task_pages_heap_used += npages;
367         }
368
369         exit_critical_section();
370
371         /* if not allowed to reserve more pages */
372         if (err != NO_ERROR) {
373                 dprintf(INFO, "TASK MEM => too many pages (%d) used for tasks\n",
374                         task_pages_heap_used);
375                 goto exit;
376         }
377
378         /* setup a task load pending object with a unique handle */
379         task_add_new_pending(tp, load_addr, byte_size, TASK_PSTATE_MEMBUF);
380
381         /* Must not fail after this point... */
382         *handle_p = tp->tp_handle;
383
384         dprintf(SPEW, "TASK MEM allocated (handle 0x%x) => app start=0x%x (%d pages) [tasks pages used %d]\n",
385                 *handle_p, (uint32_t)load_addr, npages, task_pages_heap_used);
386
387         if (0) {
388         exit:
389                 if (tp)
390                         free(tp);
391
392                 if (load_addr)
393                         heap_free((void *)load_addr);
394
395                 if (err == NO_ERROR)
396                         err = ERR_GENERIC;
397         }
398
399         return err;
400 }
401
402 void task_dealloc_memory(vaddr_t vaddr, u_int task_byte_size)
403 {
404         u_int npages = 0;
405
406         ASSERT(vaddr);
407         ASSERT(task_byte_size > 0);
408         ASSERT(original_heap_start <= vaddr && vaddr <= original_heap_end);
409
410         npages = ROUNDUP(task_byte_size, PAGE_SIZE) / PAGE_SIZE;
411
412         ASSERT(task_pages_heap_used >= npages);
413
414         heap_free((void *)vaddr);
415
416         enter_critical_section();
417         task_pages_heap_used -= npages;
418         exit_critical_section();
419 }
420
421 static status_t task_dealloc_app_load_memory_tp(task_pending_t *tp)
422 {
423         status_t err = NO_ERROR;
424         u_int npages = 0;
425         u_int byte_size = 0;
426         vaddr_t vaddr = 0;
427         u_int used_pages = task_pages_heap_used;
428
429         if (!tp) {
430                 err = ERR_TASK_GENERIC;
431                 goto exit;
432         }
433
434         vaddr     = tp->tp_task_tlk_addr;
435         byte_size = tp->tp_task_size;
436
437         if (!vaddr || byte_size <= 0) {
438                 err = ERR_TASK_GENERIC;
439                 goto exit;
440         }
441
442         task_dealloc_memory(vaddr, byte_size);
443
444         npages = ROUNDUP(byte_size, PAGE_SIZE) / PAGE_SIZE;
445         if (used_pages < npages)
446                 dprintf(INFO, "TASK MEM (handle 0x%x) dealloc INCONSISTENCY => task addr 0x%x (%d pages) [tasks pages used %d]\n",
447                         tp->tp_handle, (uint32_t)vaddr, npages, used_pages);
448         else
449                 dprintf(INFO, "TASK MEM (handle 0x%x) dealloc => task addr 0x%x (%d pages) [tasks pages used %d]\n",
450                         tp->tp_handle, (uint32_t)vaddr, npages, used_pages);
451
452         if (0) {
453         exit:
454                 if (err == NO_ERROR)
455                         err = ERR_GENERIC;
456         }
457         return err;
458 }
459
460 static status_t task_dealloc_app_load_memory(uint32_t handle)
461 {
462         status_t err = NO_ERROR;
463         task_pending_t *tp = NULL;
464
465         tp = task_find_pending(handle);
466         if (!tp) {
467                 dprintf(SPEW, "%s: task handle unknown 0x%x\n",
468                         __func__, handle);
469                 err = ERR_NOT_FOUND;
470                 goto exit;
471         }
472
473         err = task_dealloc_app_load_memory_tp(tp);
474
475         free(tp);
476         tp = NULL;
477
478         if (0) {
479         exit:
480                 if (err == NO_ERROR)
481                         err = ERR_GENERIC;
482         }
483         return err;
484 }
485
486 /* @brief Override manifest properties unless manifest is immutable.
487  *
488  * Installer task starting a loaded task may restrict the manifest options
489  * dynamically or prevent a task from being run (after verifying the
490  * manifest options).
491  *
492  * Modifications requested to manifest flagged as immutable are ignored.
493  */
494 static status_t task_property_override(task_t *taskp, task_restrictions_t *tr)
495 {
496         status_t err = NO_ERROR;
497         uint32_t size;
498
499         if (!taskp || !tr) {
500                 err = ERR_TASK_GENERIC;
501                 goto exit;
502         }
503
504         if ((taskp->props.initial_state & OTE_MANIFEST_TASK_ISTATE_IMMUTABLE) == 0) {
505                 if (tr->min_stack_size > 0) {
506                         size = ROUNDUP(tr->min_stack_size, PAGE_SIZE);
507                         taskp->props.min_stack_size = size;
508                         dprintf(INFO, "Loaded task stack size set to %d bytes\n",
509                                 taskp->props.min_stack_size);
510                 }
511
512                 if (tr->min_heap_size > 0) {
513                         size = ROUNDUP(tr->min_heap_size, PAGE_SIZE);
514                         taskp->props.min_heap_size = size;
515                         dprintf(INFO, "Loaded task heap size set to %d bytes\n",
516                                 taskp->props.min_heap_size);
517                 }
518
519                 /* override the task name if set */
520                 if (tr->task_name[0])
521                         task_set_name(taskp, tr->task_name);
522         }
523
524         if (0) {
525         exit:
526                 if (err == NO_ERROR)
527                         err = ERR_GENERIC;
528         }
529         return err;
530 }
531
532 /* @brief unmap task from TA memory at step#2/3 of task loading before
533  * the binary is parsed.
534  */
535 static status_t task_unmap_app_mem_from_ta(task_t *taskp, uint32_t handle)
536 {
537         status_t err = NO_ERROR;
538         task_pending_t *tp = NULL;
539         task_map_t *mptr = NULL;
540
541         if (!taskp) {
542                 err = ERR_INVALID_ARGS;
543                 goto exit;
544         }
545
546         tp = task_find_pending(handle);
547
548         if (!tp) {
549                 dprintf(SPEW, "%s: task handle unknown 0x%x\n",
550                         __func__, handle);
551                 err = ERR_NOT_FOUND;
552                 goto exit;
553         }
554
555         if (tp->tp_state != TASK_PSTATE_TA_MAPPED) {
556                 dprintf(CRITICAL, "%s: task handle 0x%x in wrong state: %d\n",
557                         __func__, handle, tp->tp_state);
558                 err = ERR_TASK_GENERIC;
559                 goto exit;
560         }
561
562         /*
563          * Unmap the application install buffer from the installer
564          * TA memory virtual address before doing anything with the TA
565          * copied data (for security reasons).
566          */
567         mptr = task_find_mapping(taskp, tp->tp_task_ta_addr, tp->tp_task_size);
568         if (!mptr) {
569                 dprintf(CRITICAL, "Can't find mapped memory from task address space\n");
570                 err = ERR_NOT_FOUND;
571                 goto exit;
572         }
573
574         arch_task_unmap_memory(taskp, mptr);
575         dprintf(SPEW,
576                 "Unmapped task map memory <0%08lx, %d bytes> from the calling task\n",
577                 tp->tp_task_ta_addr, tp->tp_task_size);
578
579         task_push_pending(tp, TASK_PSTATE_TA_UNMAPPED);
580
581         if (0) {
582         exit:
583                 /* released by caller */
584                 if (tp)
585                         task_push_pending(tp, TASK_PSTATE_INVALID);
586
587                 if (err == NO_ERROR)
588                         err = ERR_GENERIC;
589         }
590         return err;
591 }
592
593 /* @brief Copy task properties to task info.
594  */
595 static void task_get_config(task_info_t *ti, task_t *taskp)
596 {
597         if (ti)
598                 memset(ti, 0, sizeof(task_info_t));
599
600         if (taskp && ti) {
601                 memcpy(&ti->uuid, &taskp->props.uuid,
602                        sizeof(taskp->props.uuid));
603
604 #define TASK_COPY_PROPERTY(to,from,field) (to)->field = (from)->props.field
605
606                 TASK_COPY_PROPERTY(ti,taskp,manifest_exists);
607                 TASK_COPY_PROPERTY(ti,taskp,multi_instance);
608                 TASK_COPY_PROPERTY(ti,taskp,min_stack_size);
609                 TASK_COPY_PROPERTY(ti,taskp,min_heap_size);
610                 TASK_COPY_PROPERTY(ti,taskp,map_io_mem_cnt);
611                 TASK_COPY_PROPERTY(ti,taskp,restrict_access);
612                 TASK_COPY_PROPERTY(ti,taskp,authorizations);
613                 TASK_COPY_PROPERTY(ti,taskp,initial_state);
614
615 #undef TASK_COPY_PROPERTY
616
617                 memcpy(ti->task_name, taskp->task_name,
618                        sizeof(taskp->task_name));
619
620                 ti->task_name[sizeof(ti->task_name) - 1] = '\000';
621
622                 memcpy(ti->task_private_data, taskp->task_private_data,
623                        sizeof(taskp->task_private_data));
624         }
625 }
626
627 /* @brief Parse loaded task binary in TLK memory at step#2/3 of task loading.
628  */
629 static status_t task_parse_app(uint32_t handle, task_info_t *ti)
630 {
631         status_t err = NO_ERROR;
632         task_pending_t *tp = NULL;
633
634         tp = task_find_pending(handle);
635         if (!tp) {
636                 dprintf(SPEW, "%s: task handle unknown 0x%x\n",
637                         __func__, handle);
638                 err = ERR_NOT_FOUND;
639                 goto exit;
640         }
641
642         if (tp->tp_state != TASK_PSTATE_TA_UNMAPPED) {
643                 dprintf(CRITICAL, "%s: task handle 0x%x in wrong state: %d\n",
644                         __func__, handle, tp->tp_state);
645                 err = ERR_TASK_GENERIC;
646                 goto exit;
647         }
648
649         /* prepare task based on static app data in buffer */
650         err = task_prepare((char *)tp->tp_task_tlk_addr, tp->tp_task_size,
651                            &tp->tp_task, NULL, TASK_TYPE_LOADED);
652         if (err != NO_ERROR) {
653                 dprintf(CRITICAL, "%s: loaded task preparation failed (%d)\n",
654                         __func__, err);
655                 goto exit;
656         }
657
658         if (!tp->tp_task.props.manifest_exists) {
659                 dprintf(INFO, "%s: loaded task image has no manifest\n", __func__);
660         }
661
662         /* copy selected manifest config options to be passed back to caller */
663         task_get_config(ti, &tp->tp_task);
664
665         task_push_pending(tp, TASK_PSTATE_PREPARED);
666
667         if (0) {
668         exit:
669                 /* released by caller */
670                 if (tp)
671                         task_push_pending(tp, TASK_PSTATE_INVALID);
672
673                 if (err == NO_ERROR)
674                         err = ERR_GENERIC;
675         }
676         return err;
677 }
678
679 /* @brief Start loaded application with manifest restrictions at step#3/3.
680  */
681 static status_t task_run_app(uint32_t handle, uint32_t reject_task, task_restrictions_t *tr)
682 {
683         status_t err = NO_ERROR;
684         task_pending_t *tp = NULL;
685         task_t *taskp = NULL;
686         int task_registered = 0;
687
688         tp = task_find_pending(handle);
689         if (!tp) {
690                 dprintf(SPEW, "%s: task handle unknown 0x%x\n",
691                         __func__, handle);
692                 err = ERR_NOT_FOUND;
693                 goto exit;
694         }
695
696         /* a task can be rejected at any state; this triggers resource cleanup */
697         if (!tr || reject_task) {
698                 dprintf(INFO, "%s: task handle 0x%x rejected in state: %d\n",
699                         __func__, handle, tp->tp_state);
700
701                 task_dealloc_app_load_memory_tp(tp);
702         } else {
703                 if (tp->tp_state != TASK_PSTATE_PREPARED) {
704                         dprintf(CRITICAL, "%s: task handle 0x%x in wrong state: %d\n",
705                                 __func__, handle, tp->tp_state);
706                         err = ERR_TASK_GENERIC;
707                         goto exit;
708                 }
709
710                 taskp = &tp->tp_task;
711
712                 /*
713                  * Any possible task restrictions are enforced here
714                  *
715                  * If loading an image without manifest is required =>
716                  * add support for setting UUID and other manifest
717                  * configured options by the property override calls.
718                  *
719                  * Currently this is NOT SUPPORTED but it is simple to
720                  * add to the task_property_override().
721                  *
722                  * Doing so would enable the installer to control all
723                  * aspects of app install (task loading), including
724                  * the application identity and all options (e.g.
725                  * the task config data modification).
726                  *
727                  * NOTE: Currently all loaded tasks must contain a
728                  * built-in manifest.
729                  */
730                 err = task_property_override(taskp, tr);
731                 if (err != NO_ERROR) {
732                         dprintf(CRITICAL, "%s: task install 0x%x rejected by override error %d\n",
733                                 __func__, handle, err);
734                         goto exit;
735                 }
736
737                 /*
738                  * At this point the task must either have manifest loaded from signed image
739                  * or contain one created by the property override above.
740                  */
741                 if (!taskp->props.manifest_exists) {
742                         dprintf(CRITICAL, "%s: Invalid task image\n", __func__);
743                         err = ERR_NOT_VALID;
744                         goto exit;
745                 }
746
747                 /*
748                  * Atomically commit task (and assign the index) to the known task_list
749                  * unless there is an error. TASKP value swapped to track the registered
750                  * task header (old object is cleared in the call).
751                  *
752                  * tp->tp_task is cleared by task_register.
753                  */
754                 err = task_register(&taskp);
755
756                 if (err != NO_ERROR) {
757                         dprintf(CRITICAL, "%s: loaded task %d registration failed (%d)\n",
758                                 __func__, task_get_count(), err);
759                         goto exit;
760                 }
761
762                 task_registered++;
763
764                 /*
765                  * Init task and start it
766                  */
767                 err = task_init_one_task(taskp);
768                 if (err != NO_ERROR) {
769                         status_t err2 = NO_ERROR;
770                         uint32_t tindex = taskp->task_index;
771
772                         dprintf(CRITICAL, "Loaded task#%u init failed (0x%x), unloading...\n",
773                                 tindex, err);
774
775                         err2 = task_unload(&taskp);
776                         if (err2 != NO_ERROR) {
777                                 dprintf(CRITICAL, "Unloading the failed task#%u failed: (0x%x)\n",
778                                         tindex, err2);
779                         }
780                         goto exit;
781                 }
782
783                 task_load_counter++;
784         }
785
786         /*
787          * Already removed from pending task list and now junked
788          * because task is now active.
789          *
790          * Just for completeness, advance the state machine before killing object.
791          */
792         tp->tp_state = TASK_PSTATE_READY;
793         free(tp);
794         tp = NULL;
795
796         if (0) {
797         exit:
798                 if (tp) {
799                         if (!task_registered)
800                                 task_dealloc_app_load_memory_tp(tp);
801
802                         free(tp);
803                 }
804
805                 if (err == NO_ERROR)
806                         err = ERR_GENERIC;
807         }
808         return err;
809 }
810
811 /**
812  * @brief Change name of the task
813  */
814 void task_set_name(task_t *task, const char *name)
815 {
816         if (task) {
817                 if (!name || !name[0])
818                         task->task_name[0] = '\000';
819                 else
820                         strlcpy(task->task_name, name, sizeof(task->task_name));
821         }
822 }
823
824 #ifdef DEBUG
825
826 /* reference to end of the binary and end of heap */
827 extern int _end;
828 extern int _heap_end;
829
830 /* debug: print system info to console.
831  *
832  * For R&D only, should disable from production builds.
833  */
834 void task_system_info(te_system_info_args_t *args)
835 {
836         if (args->si_type == 41) {
837                 dprintf(INFO, "Kernel thread dump:\n");
838                 dump_all_threads();
839         } else {
840
841 #define HEAP_LEN ((u_int)_heap_end - (u_int)&_end)
842
843                 dprintf(INFO, "HEAP start (orig): 0x%x\n", (u_int)original_heap_start);
844                 dprintf(INFO, "HEAP end   (orig): 0x%x\n", (u_int)original_heap_end);
845
846                 dprintf(INFO, "HEAP start (end of binary == &_end) %p\n", &_end);
847                 dprintf(INFO, "HEAP end (end_of_memory == _heap_end) %p\n",
848                         (void *)_heap_end);
849                 dprintf(INFO, "HEAP size (_heap_end-&_end)=%u (0x%x) bytes\n",
850                         HEAP_LEN, HEAP_LEN);
851
852                 dprintf(INFO, "Number of active tasks: %d\n",
853                         task_get_active_count());
854
855                 dprintf(INFO, "sizeof(task_t): %d bytes\n", sizeof(task_t));
856
857                 dprintf(INFO, "Heap pages used for tasks: %d\n", task_pages_heap_used);
858
859                 dprintf(INFO, "Heap pages for tasks: left %d (out of %d)\n",
860                         task_pages_heap_max - task_pages_heap_used,
861                         task_pages_heap_max);
862
863                 dprintf(INFO, "Tasks loaded since boot: %u\n", task_load_counter);
864                 dprintf(INFO, "Tasks unloaded since boot: %u\n", task_get_unload_counter());
865         }
866 }
867 #endif /* DEBUG */
868
869 /* handlers for task_request_handler() */
870
871 static int tlk_handle_app_memory_request(te_app_load_memory_request_args_t *args)
872 {
873         vaddr_t     ta_vaddr    = NULL;
874         uint32_t    handle      = 0;
875         task_t     *taskp       = current_thread->arch.task;
876
877         if (!args)
878                 return -EINVAL;
879
880         dprintf(SPEW, "%s: mem request app size %d bytes\n",
881                 __func__, args->app_size);
882
883         task_print_uuid(INFO, "Map task memory request by ", taskp);
884
885         /*
886          * Simple manifest based permission allowing a task to install
887          * other tasks.
888          */
889         if (!task_allowed_to_load_tasks(taskp)) {
890                 task_print_uuid(CRITICAL, "Client tried to perform "
891                                 "an operation for which they are "
892                                 "not permitted ", taskp);
893                 return -EACCES;
894         }
895
896         {
897                 status_t err = NO_ERROR;
898
899                 err = task_request_app_load_memory(args->app_size, &handle);
900                 if (err != NO_ERROR)  {
901                         dprintf(CRITICAL, "Failed to allocate app memory (%d bytes, err %d)\n",
902                                 args->app_size, err);
903                         return ((err == ERR_NO_MEMORY) ? -ENOMEM : -EINVAL);
904                 }
905
906                 dprintf(SPEW, "Handle for app loading 0x%x, %d bytes\n",
907                         handle, args->app_size);
908
909                 err = task_map_memory_to_ta(taskp, handle, &ta_vaddr);
910                 if (err != NO_ERROR || !ta_vaddr) {
911                         status_t err2 = task_dealloc_app_load_memory(handle);
912                         if (err2 != NO_ERROR)  {
913                                 dprintf(CRITICAL, "Failed to dealloc app handle 0x%x, %d bytes, err %d\n",
914                                         handle, args->app_size, err2);
915                         }
916                         return -ENOMEM;
917                 }
918         }
919
920         /* pass shared buffer TA vaddr back to the TA */
921         args->app_addr   = ta_vaddr;
922         /* handle to refer to the pending task load */
923         args->app_handle = handle;
924
925         /*
926          * app_size field is unmodified; still contains the requested
927          * mem size but the actual shared buffer size is rounded
928          * to next page boundary.
929          */
930         return 0;
931 }
932
933 static void map_task_info_to_te(te_task_info_t *to, task_info_t *from)
934 {
935         if (to)
936                 memset(to, 0, sizeof(te_task_info_t));
937
938         if (from && to) {
939                 memcpy(&to->uuid, &from->uuid, sizeof(from->uuid));
940
941 #define TASK_COPY_PROPERTY(out,in,field) (out)->field = (in)->field
942
943                 TASK_COPY_PROPERTY(to,from,manifest_exists);
944                 TASK_COPY_PROPERTY(to,from,multi_instance);
945                 TASK_COPY_PROPERTY(to,from,min_stack_size);
946                 TASK_COPY_PROPERTY(to,from,min_heap_size);
947                 TASK_COPY_PROPERTY(to,from,map_io_mem_cnt);
948                 TASK_COPY_PROPERTY(to,from,restrict_access);
949                 TASK_COPY_PROPERTY(to,from,authorizations);
950                 TASK_COPY_PROPERTY(to,from,initial_state);
951
952 #undef TASK_COPY_PROPERTY
953
954                 memcpy(to->task_name, from->task_name, OTE_TASK_NAME_MAX_LENGTH);
955                 memcpy(to->task_private_data,
956                        from->task_private_data, OTE_TASK_PRIVATE_DATA_LENGTH);
957         }
958 }
959
960 static int tlk_handle_app_prepare(te_app_prepare_args_t *args)
961 {
962         status_t err = NO_ERROR;
963         task_t *taskp = current_thread->arch.task;
964         task_info_t ti;
965
966         if (!args)
967                 return -EINVAL;
968
969         dprintf(INFO, "Parsing app handle 0x%x\n", args->app_handle);
970
971         if (!task_allowed_to_load_tasks(taskp)) {
972                 task_print_uuid(CRITICAL, "Client tried to perform "
973                                 "an operation for which they are "
974                                 "not permitted ", taskp);
975                 return -EACCES;
976         }
977
978         /*
979          * Remove the shared memory mapping from installer
980          * memory map. After this only TLK will see the application.
981          */
982         err = task_unmap_app_mem_from_ta(taskp, args->app_handle);
983         if (err != NO_ERROR) {
984                 dprintf(INFO, "Could not unmap TA shared memory (%d)\n", err);
985                 task_dealloc_app_load_memory(args->app_handle);
986                 return -EINVAL;
987         }
988
989         /*
990          * Parse application
991          */
992         memset(&ti, 0, sizeof(ti));
993         err = task_parse_app(args->app_handle, &ti);
994         if (err != NO_ERROR) {
995                 dprintf(INFO, "Could parse loaded application (%d)\n", err);
996                 task_dealloc_app_load_memory(args->app_handle);
997                 return -EINVAL;
998         }
999         map_task_info_to_te(&args->te_task_info, &ti);
1000
1001         return 0;
1002 }
1003
1004 static int get_manifest_mapping(task_t *task, te_memory_mapping_t *map)
1005 {
1006         u_int i = 0;
1007         u_int found     = 0;
1008         u_int map_index = 0;
1009
1010         if (! task || ! map)
1011                 return -EINVAL;
1012
1013         for (i = 0; i < task->props.config_entry_cnt; i++) {
1014                 if (task->props.config_blob[i] == OTE_CONFIG_KEY_MAP_MEM) {
1015                         if (map_index == map->map_index) {
1016
1017                                 /* found the specified mapping by index */
1018                                 map->map_id     = task->props.config_blob[++i];
1019                                 map->map_offset = task->props.config_blob[++i];
1020                                 map->map_size   = task->props.config_blob[++i];
1021
1022                                 found++;
1023                                 break;
1024                         } else {
1025                                 /* wrong mapping, skip the 3 fields */
1026                                 i += 3;
1027                         }
1028
1029                         map_index++;
1030                 } else {
1031                         /* all other config options take 1 data value */
1032                         i++;
1033                 }
1034         }
1035
1036         if (!found)
1037                 return -ESRCH;
1038
1039         return 0;
1040 }
1041
1042 /*
1043  * Add an API to fetch the manifest mappings from a pending task using its handle
1044  * (i.e. when task is being loaded).
1045  *
1046  * This is an installer only API to enable decisions if the task
1047  * needs to be rejected due to unauthorized memory mappings. The caller must
1048  * reject the task on error, this routine does not do it.
1049  */
1050 static int tlk_get_pending_mapping(te_get_pending_map_args_t *args)
1051 {
1052         int rval = 0;
1053         task_t *taskp = current_thread->arch.task;
1054         task_pending_t *tp = NULL;
1055
1056         if (!args)
1057                 return -EINVAL;
1058
1059         if (!task_allowed_to_load_tasks(taskp)) {
1060                 task_print_uuid(CRITICAL, "Client tried to perform "
1061                                 "an operation for which they are "
1062                                 "not permitted ", taskp);
1063                 rval = -EACCES;
1064                 goto exit;
1065         }
1066
1067         tp = task_find_pending(args->pm_handle);
1068         if (!tp) {
1069                 dprintf(SPEW, "%s: task handle unknown 0x%x\n",
1070                         __func__, args->pm_handle);
1071                 rval = -ENOENT;
1072                 goto exit;
1073         }
1074
1075         /* Do not reject task when fetching a non-existent mapping.
1076          * Just return a not found error but allow install to proceed or
1077          * installer to reject the task.
1078          */
1079         if (tp->tp_state != TASK_PSTATE_PREPARED) {
1080                 dprintf(INFO, "%s: task handle 0x%x in wrong state: %d\n",
1081                         __func__, args->pm_handle, tp->tp_state);
1082                 rval = -EINVAL;
1083         } else if (tp->tp_task.props.map_io_mem_cnt < (args->pm_map.map_index + 1)) {
1084                 dprintf(INFO, "Task manifest does not contain %d memory mappings",
1085                         args->pm_map.map_index + 1);
1086                 rval = -ESRCH;
1087         } else {
1088                 if (get_manifest_mapping(&tp->tp_task, &args->pm_map)) {
1089                         dprintf(INFO, "Task manifest does not contain mapping at index %d",
1090                                 args->pm_map.map_index);
1091                         rval = -ESRCH;
1092                 }
1093         }
1094
1095         task_push_pending(tp, tp->tp_state);
1096
1097 exit:
1098         return rval;
1099 }
1100
1101 /*
1102  * Copy selected non-security related fields that the installer wants
1103  * to enforce to the task when it starts. Zero field values are not-used.
1104  *
1105  * This is just a type mapping, properties are set later in task_property_override.
1106  */
1107 static void map_task_app_restrictions(task_restrictions_t *to,
1108                                       te_task_restrictions_t *from)
1109 {
1110         if (to)
1111                 memset(to, 0, sizeof(task_restrictions_t));
1112
1113         if (from && to) {
1114
1115                 to->min_stack_size = from->min_stack_size;
1116                 to->min_heap_size = from->min_heap_size;
1117
1118                 memcpy(to->task_name, from->task_name, OTE_TASK_NAME_MAX_LENGTH);
1119         }
1120 }
1121
1122 static int tlk_handle_app_start(te_app_start_args_t *args)
1123 {
1124         status_t err = NO_ERROR;
1125         task_t *taskp = current_thread->arch.task;
1126         task_restrictions_t task_restrictions;
1127         const char *op_info = "start";
1128
1129         if (!args)
1130                 return -EINVAL;
1131
1132         if (!task_allowed_to_load_tasks(taskp)) {
1133                 task_print_uuid(CRITICAL, "Client tried to perform "
1134                                 "an operation for which they are "
1135                                 "not permitted ", taskp);
1136                 return -EACCES;
1137         }
1138
1139         map_task_app_restrictions(&task_restrictions, &args->app_restrictions);
1140
1141         if (args->app_reject)
1142                 op_info = "reject";
1143
1144         dprintf(INFO, "%s app with handle 0x%x\n", op_info, args->app_handle);
1145
1146         err = task_run_app(args->app_handle, args->app_reject, &task_restrictions);
1147         if (err != NO_ERROR) {
1148                 /* Do not log when rejecting a task that no longer exists */
1149                 if (!args->app_reject || (err != ERR_NOT_FOUND))
1150                         dprintf(CRITICAL, "Could not %s loaded application (%d)\n",
1151                                 op_info, err);
1152                 return -EINVAL;
1153         }
1154
1155         return 0;
1156 }
1157
1158 /*
1159  * A bit strict: only authorized apps can list which tasks are installed
1160  * in the system. However, this is a privileged operation also in GP specs.
1161  *
1162  * Copy the UUID and TASK_NAME of the indicated task to the arg buf.
1163  * If the task has no defined name the app_name field is zeroed.
1164  */
1165 static int tlk_list_apps(te_app_list_args_t *args)
1166 {
1167         task_t *taskp   = current_thread->arch.task;
1168         task_t *task    = NULL;
1169         task_info_t ti;
1170
1171         if (!args)
1172                 return -EINVAL;
1173
1174         if (!task_allowed_to_load_tasks(taskp)) {
1175                 task_print_uuid(CRITICAL, "Client tried to perform "
1176                                 "an operation for which they are "
1177                                 "not permitted ", taskp);
1178                 return -EACCES;
1179         }
1180
1181         args->app_type = TASK_TYPE_UNKNOWN;
1182         args->app_state = TASK_STATE_UNKNOWN;
1183         memset(&args->app_info, 0, sizeof(args->app_info));
1184
1185         /* task at this or any larger index does not exist */
1186         if (args->app_index > task_get_count())
1187                 return -ENOENT;
1188
1189         task = task_find_task_by_index(args->app_index);
1190         if (!task) {
1191                 /* task at index does not exist */
1192                 return -ESRCH;
1193         }
1194
1195         /*
1196          * Otherwise set up the UUID and other info of the specified task to the
1197          * IOCTL result.
1198          */
1199         args->app_type = task->task_type;
1200         args->app_state = task->task_state;
1201
1202         task_get_config(&ti, task);
1203         map_task_info_to_te(&args->app_info, &ti);
1204
1205         return 0;
1206 }
1207
1208 static int tlk_task_get_info(te_get_task_info_t *args)
1209 {
1210         task_t *taskp   = current_thread->arch.task;
1211         task_t *task    = NULL;
1212         task_info_t ti;
1213
1214         if (!args)
1215                 return -EINVAL;
1216
1217         /* Any task is authorized to fetch it's own manifest information (SELF).
1218          * Installers are authorized to fetch it from any task.
1219          */
1220         if (!task_allowed_to_load_tasks(taskp) &&
1221             (args->gti_request_type != OTE_GET_TASK_INFO_REQUEST_SELF)) {
1222                 task_print_uuid(CRITICAL, "Client tried to perform "
1223                                 "an operation for which they are "
1224                                 "not permitted ", taskp);
1225                 return -EACCES;
1226         }
1227
1228         switch (args->gti_request_type) {
1229         case OTE_GET_TASK_INFO_REQUEST_INDEX:
1230                 /* task at this or any larger index does not exist */
1231                 if (args->gtiu_index > task_get_count())
1232                         return -ENOENT;
1233
1234                 task = task_find_task_by_index(args->gtiu_index);
1235                 break;
1236         case OTE_GET_TASK_INFO_REQUEST_UUID:
1237                 task = task_find_task_by_uuid(&args->gtiu_uuid);
1238                 break;
1239         case OTE_GET_TASK_INFO_REQUEST_SELF:
1240                 task = taskp;
1241                 break;
1242         default:
1243                 task = NULL;
1244                 break;
1245         }
1246
1247         if (!task)
1248                 return -ENOENT;
1249
1250         memset(&ti, 0, sizeof(ti));
1251         task_get_config(&ti, task);
1252
1253         args->gti_state = task->task_state;
1254         map_task_info_to_te(&args->gti_info, &ti);
1255
1256         return 0;
1257 }
1258
1259 static int tlk_task_get_mapping(te_get_task_mapping_t *args)
1260 {
1261         task_t *taskp   = current_thread->arch.task;
1262         task_t *task    = NULL;
1263
1264         if (!args)
1265                 return -EINVAL;
1266
1267         /* Any task is authorized to fetch it's own mapping information (SELF).
1268          * Installers are authorized to fetch it from any task.
1269          */
1270         if (!task_allowed_to_load_tasks(taskp) &&
1271             (args->gmt_request_type != OTE_GET_TASK_INFO_REQUEST_SELF)) {
1272                 task_print_uuid(CRITICAL, "Client tried to perform "
1273                                 "an operation for which they are "
1274                                 "not permitted ", taskp);
1275                 return -EACCES;
1276         }
1277
1278         switch (args->gmt_request_type) {
1279         case OTE_GET_TASK_INFO_REQUEST_INDEX:
1280                 /* task at this or any larger index does not exist */
1281                 if (args->gmtu_index > task_get_count())
1282                         return -ENOENT;
1283
1284                 task = task_find_task_by_index(args->gmtu_index);
1285                 break;
1286         case OTE_GET_TASK_INFO_REQUEST_UUID:
1287                 task = task_find_task_by_uuid(&args->gmtu_uuid);
1288                 break;
1289         case OTE_GET_TASK_INFO_REQUEST_SELF:
1290                 task = taskp;
1291                 break;
1292         default:
1293                 task = NULL;
1294                 break;
1295         }
1296
1297         if (!task)
1298                 return -ENOENT;
1299
1300         return get_manifest_mapping(task, &args->gmt_map);
1301 }
1302
1303 static int tlk_task_unload(te_app_unload_args_t *args)
1304 {
1305         status_t err  = NO_ERROR;
1306         task_t *taskp = current_thread->arch.task;
1307         task_t *target_task = NULL;
1308
1309         if (!args)
1310                 return -EINVAL;
1311
1312         if (!task_allowed_to_load_tasks(taskp)) {
1313                 task_print_uuid(CRITICAL, "Client tried to perform "
1314                                 "an operation for which they are "
1315                                 "not permitted ", taskp);
1316                 return -EACCES;
1317         }
1318
1319         switch (args->tid_type) {
1320         case OTE_APP_ID_INDEX:
1321                 /* task at this or any larger index does not exist */
1322                 if (args->tid_index > task_get_count())
1323                         return -ENOENT;
1324
1325                 target_task = task_find_task_by_index(args->tid_index);
1326                 break;
1327         case OTE_APP_ID_UUID:
1328                 target_task = task_find_task_by_uuid(&args->tid_uuid);
1329                 break;
1330         default:
1331                 return -EINVAL;
1332         }
1333
1334         if (!target_task)
1335                 return -ESRCH;
1336
1337         task_print_uuid(INFO, "Request to unload task ", target_task);
1338
1339         err = task_unload(&target_task);
1340         if (err != NO_ERROR) {
1341                 switch (err) {
1342                 case ERR_NOT_FOUND:   return -ENOENT;
1343                 case ERR_NOT_ALLOWED: return -EACCES;
1344                 default: return -EINVAL;
1345                 }
1346         }
1347
1348         return 0;
1349 }
1350
1351 /*
1352  * Block an active task so it does not accept new sessions.
1353  *
1354  * Note that after blocking the last task which has installer privileges
1355  * you can no longer unblock any blocked tasks in the system.
1356  */
1357 static int tlk_task_block(te_app_block_args_t *args)
1358 {
1359         task_t *taskp = current_thread->arch.task;
1360         task_t *target_task  = NULL;
1361
1362         if (!args)
1363                 return -EINVAL;
1364
1365         if (!task_allowed_to_load_tasks(taskp)) {
1366                 task_print_uuid(CRITICAL, "Client tried to perform "
1367                                 "an operation for which they are "
1368                                 "not permitted ", taskp);
1369                 return -EACCES;
1370         }
1371
1372         switch (args->tid_type) {
1373         case OTE_APP_ID_INDEX:
1374                 /* task at this or any larger index does not exist */
1375                 if (args->tid_index > task_get_count())
1376                         return -ENOENT;
1377
1378                 target_task = task_find_task_by_index(args->tid_index);
1379                 break;
1380         case OTE_APP_ID_UUID:
1381                 target_task = task_find_task_by_uuid(&args->tid_uuid);
1382                 break;
1383         default:
1384                 return -EINVAL;
1385         }
1386
1387         if (!target_task)
1388                 return -ESRCH;
1389
1390         switch(target_task->task_state) {
1391         case TASK_STATE_BLOCKED:
1392         case TASK_STATE_ACTIVE:
1393                 target_task->task_state = TASK_STATE_BLOCKED;
1394                 task_print_uuid(INFO, "Blocked task ", target_task);
1395                 break;
1396         default:
1397                 dprintf(INFO, "Request to block task#%d in state %d -- rejected\n",
1398                         target_task->task_index,
1399                         target_task->task_state);
1400                 return -EINVAL;
1401         }
1402
1403         return 0;
1404 }
1405
1406 static int tlk_task_unblock(te_app_block_args_t *args)
1407 {
1408         task_t *taskp = current_thread->arch.task;
1409         task_t *target_task  = NULL;
1410
1411         if (!args)
1412                 return -EINVAL;
1413
1414         if (!task_allowed_to_load_tasks(taskp)) {
1415                 task_print_uuid(CRITICAL, "Client tried to perform "
1416                                 "an operation for which they are "
1417                                 "not permitted ", taskp);
1418                 return -EACCES;
1419         }
1420
1421         switch (args->tid_type) {
1422         case OTE_APP_ID_INDEX:
1423                 /* task at this or any larger index does not exist */
1424                 if (args->tid_index > task_get_count())
1425                         return -ENOENT;
1426
1427                 target_task = task_find_task_by_index(args->tid_index);
1428                 break;
1429         case OTE_APP_ID_UUID:
1430                 target_task = task_find_task_by_uuid(&args->tid_uuid);
1431                 break;
1432         default:
1433                 return -EINVAL;
1434         }
1435
1436         if (!target_task)
1437                 return -ESRCH;
1438
1439         switch(target_task->task_state) {
1440         case TASK_STATE_BLOCKED:
1441                 target_task->task_state = TASK_STATE_ACTIVE;
1442                 task_print_uuid(INFO, "Unblocked task ", target_task);
1443                 break;
1444         default:
1445                 dprintf(INFO, "Request to unblock task#%d in state %d -- rejected\n",
1446                         target_task->task_index,
1447                         target_task->task_state);
1448                 return -EINVAL;
1449         }
1450
1451         return 0;
1452 }
1453
1454 /*
1455  * Called by syscall OTE_IOCTL_TASK_REQUEST ioctl handler
1456  */
1457 int task_request_handler(te_task_request_args_t *args)
1458 {
1459         int retval = 0;
1460
1461         if (!args) {
1462                 retval = -EINVAL;
1463                 goto exit;
1464         }
1465
1466         switch (args->ia_opcode) {
1467         case OTE_TASK_OP_MEMORY_REQUEST:
1468                 retval = tlk_handle_app_memory_request(&args->ia_load_memory_request);
1469                 break;
1470
1471         case OTE_TASK_OP_PREPARE:
1472                 retval = tlk_handle_app_prepare(&args->ia_prepare);
1473                 break;
1474
1475         case OTE_TASK_OP_PENDING_MAPPING:
1476                 retval = tlk_get_pending_mapping(&args->ia_pending_mapping);
1477                 break;
1478
1479         case OTE_TASK_OP_START:
1480                 retval = tlk_handle_app_start(&args->ia_start);
1481                 break;
1482
1483         case OTE_TASK_OP_LIST:
1484                 retval = tlk_list_apps(&args->ia_list);
1485                 break;
1486
1487         case OTE_TASK_OP_GET_TASK_INFO:
1488                 retval = tlk_task_get_info(&args->ia_get_task_info);
1489                 break;
1490
1491         case OTE_TASK_OP_GET_MAPPING:
1492                 /* much like pending mapping above, but for existing tasks */
1493                 retval = tlk_task_get_mapping(&args->ia_get_task_mapping);
1494                 break;
1495
1496 #ifdef DEBUG
1497         case OTE_TASK_OP_SYSTEM_INFO:
1498                 task_system_info(&args->ia_system_info);
1499                 break;
1500 #endif
1501
1502         case OTE_TASK_OP_UNLOAD:
1503                 retval = tlk_task_unload(&args->ia_app_unload);
1504                 break;
1505
1506         case OTE_TASK_OP_BLOCK:
1507                 retval = tlk_task_block(&args->ia_app_block);
1508                 break;
1509
1510         case OTE_TASK_OP_UNBLOCK:
1511                 retval = tlk_task_unblock(&args->ia_app_block);
1512                 break;
1513
1514         default:
1515                 retval = -EINVAL;
1516                 break;
1517         }
1518
1519 exit:
1520         return retval;
1521 }