1 /**
2 * Copyright(c) 2011 Trusted Logic. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 *
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in
12 * the documentation and/or other materials provided with the
13 * distribution.
14 * * Neither the name Trusted Logic nor the names of its
15 * contributors may be used to endorse or promote products derived
16 * from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30
31 #if defined(__ANDROID32__)
32 #include <stddef.h>
33 #endif
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <string.h>
37
38 /*
39 * When porting to a new OS, insert here the appropriate include files
40 */
41 #include <sys/stat.h>
42 #include <errno.h>
43 #include <sys/types.h>
44 #include <fcntl.h>
45
46 #if defined(LINUX) || defined(__ANDROID32__)
47 #include <unistd.h>
48 #include <sys/resource.h>
49
50
51 #if defined(__ANDROID32__)
52 /* fdatasync does not exist on Android */
53 #define fdatasync fsync
54 #else
55 /*
56 * http://linux.die.net/man/2/fsync
57 * The function fdatasync seems to be absent of the header file
58 * in some distributions
59 */
60 int fdatasync(int fd);
61 #endif /* __ANDROID32__ */
62 #include <syslog.h>
63 #include <sys/types.h>
64 #include <sys/stat.h>
65 #include <pthread.h>
66 #include <semaphore.h>
67 #define PATH_SEPARATOR '/'
68 #endif /* LINUX || __ANDROID32__ */
69
70 #ifdef WIN32
71 #include <windows.h>
72 #include <io.h>
73 #define PATH_SEPARATOR '\\'
74 #endif
75
76 #ifdef __SYMBIAN32__
77 #include <unistd.h>
78 #include "os_symbian.h"
79 #define PATH_SEPARATOR '\\'
80 #endif
81
82 #include <stdarg.h>
83 #include <assert.h>
84
85 #include "service_delegation_protocol.h"
86
87 #include "s_version.h"
88 #include "s_error.h"
89 #include "tee_client_api.h"
90
91 /* You can define the preprocessor constant SUPPORT_DELEGATION_EXTENSION
92 if you want to pass extended options in a configuration file (option '-c').
93 It is up to you to define the format of this configuration file and the
94 extended option in the source file delegation_client_extension.c. You can
95 use extended options, e.g., to control the name of each partition file. */
96 #ifdef SUPPORT_DELEGATION_EXTENSION
97 #include "delegation_client_extension.h"
98 #endif
99
100 /*----------------------------------------------------------------------------
101 * Design notes
102 * ============
103 *
104 * This implementation of the delegation daemon supports the protocol
105 * specified in the Product Reference Manual ("Built-in Services Protocols Specification")
106 *
107 *----------------------------------------------------------------------------*/
108
109 /*----------------------------------------------------------------------------
110 * Defines and structures
111 *----------------------------------------------------------------------------*/
112 #define ECHANGE_BUFFER_INSTRUCTIONS_NB 100
113
114 #define DEFAULT_WORKSPACE_SIZE (128*1024)
115
116 /* A single shared memory block is used to contain the administrative data, the
117 instruction buffer and the workspace. The size of the instruction buffer is
118 fixed, but the size of workspace can be configured using the "-workspaceSize"
119 command-line option. */
120 typedef struct
121 {
122 DELEGATION_ADMINISTRATIVE_DATA sAdministrativeData;
123 uint32_t sInstructions[ECHANGE_BUFFER_INSTRUCTIONS_NB];
124 uint8_t sWorkspace[1/*g_nWorkspaceSize*/];
125 } DELEGATION_EXCHANGE_BUFFER;
126
127 #define MD_VAR_NOT_USED(variable) do{(void)(variable);}while(0);
128
129 #define MD_INLINE __inline
130
131 /* ----------------------------------------------
132 Traces and logs
133
134 On Linux, traces and logs go either to the console (stderr) or to the syslog.
135 When the daemon is started, the logs go to the console. Once and if the daemon
136 is detached, the logs go to syslog.
137
138 On other systems, traces and logs go systematically to stderr
139
140 The difference between traces and logs is that traces are compiled out
141 in release builds whereas logs are visible to the customer.
142
143 -----------------------------------------------*/
144 #if defined(LINUX) || (defined __ANDROID32__)
145
146 static bool bDetached = false;
147
LogError(const char * format,...)148 static MD_INLINE void LogError(const char* format, ...)
149 {
150 va_list ap;
151 va_start(ap, format);
152 if (bDetached)
153 {
154 vsyslog(LOG_ERR, format, ap);
155 }
156 else
157 {
158 fprintf(stderr, "ERROR: ");
159 vfprintf(stderr, format, ap);
160 fprintf(stderr, "\n");
161 }
162 va_end(ap);
163 }
164
LogWarning(const char * format,...)165 static MD_INLINE void LogWarning(const char* format, ...)
166 {
167 va_list ap;
168 va_start(ap, format);
169 if (bDetached)
170 {
171 vsyslog(LOG_WARNING, format, ap);
172 }
173 else
174 {
175 fprintf(stderr, "WARNING: ");
176 vfprintf(stderr, format, ap);
177 fprintf(stderr, "\n");
178 }
179 va_end(ap);
180 }
LogInfo(const char * format,...)181 static MD_INLINE void LogInfo(const char* format, ...)
182 {
183 va_list ap;
184 va_start(ap, format);
185 if (bDetached)
186 {
187 vsyslog(LOG_INFO, format, ap);
188 }
189 else
190 {
191 vfprintf(stderr, format, ap);
192 fprintf(stderr, "\n");
193 }
194 va_end(ap);
195 }
196
TRACE_ERROR(const char * format,...)197 static MD_INLINE void TRACE_ERROR(const char* format, ...)
198 {
199 #ifndef NDEBUG
200 va_list ap;
201 va_start(ap, format);
202 if (bDetached)
203 {
204 vsyslog(LOG_ERR, format, ap);
205 }
206 else
207 {
208 fprintf(stderr, "TRACE: ERROR: ");
209 vfprintf(stderr, format, ap);
210 fprintf(stderr, "\n");
211 }
212 va_end(ap);
213 #else
214 MD_VAR_NOT_USED(format);
215 #endif /* NDEBUG */
216 }
217
TRACE_WARNING(const char * format,...)218 static MD_INLINE void TRACE_WARNING(const char* format, ...)
219 {
220 #ifndef NDEBUG
221 va_list ap;
222 va_start(ap, format);
223 if (bDetached)
224 {
225 vsyslog(LOG_WARNING, format, ap);
226 }
227 else
228 {
229 fprintf(stderr, "TRACE: WARNING: ");
230 vfprintf(stderr, format, ap);
231 fprintf(stderr, "\n");
232 }
233 va_end(ap);
234 #else
235 MD_VAR_NOT_USED(format);
236 #endif /* NDEBUG */
237 }
238
TRACE_INFO(const char * format,...)239 static MD_INLINE void TRACE_INFO(const char* format, ...)
240 {
241 #ifndef NDEBUG
242 va_list ap;
243 va_start(ap, format);
244 if (bDetached)
245 {
246 vsyslog(LOG_DEBUG, format, ap);
247 }
248 else
249 {
250 fprintf(stderr, "TRACE: ");
251 vfprintf(stderr, format, ap);
252 fprintf(stderr, "\n");
253 }
254 va_end(ap);
255 #else
256 MD_VAR_NOT_USED(format);
257 #endif /* NDEBUG */
258 }
259 #elif defined __SYMBIAN32__
260 /* defined in os_symbian.h */
261
262 #elif defined NO_LOG_NO_TRACE
LogError(const char * format,...)263 static MD_INLINE void LogError(const char* format, ...)
264 {
265 MD_VAR_NOT_USED(format);
266 }
LogWarning(const char * format,...)267 static MD_INLINE void LogWarning(const char* format, ...)
268 {
269 MD_VAR_NOT_USED(format);
270 }
LogInfo(const char * format,...)271 static MD_INLINE void LogInfo(const char* format, ...)
272 {
273 MD_VAR_NOT_USED(format);
274 }
275
TRACE_ERROR(const char * format,...)276 static MD_INLINE void TRACE_ERROR(const char* format, ...)
277 {
278 MD_VAR_NOT_USED(format);
279 }
280
TRACE_WARNING(const char * format,...)281 static MD_INLINE void TRACE_WARNING(const char* format, ...)
282 {
283 MD_VAR_NOT_USED(format);
284 }
285
TRACE_INFO(const char * format,...)286 static MD_INLINE void TRACE_INFO(const char* format, ...)
287 {
288 MD_VAR_NOT_USED(format);
289 }
290
291 #else
292 /* !defined(LINUX) || !defined(__ANDROID32__) */
293
LogError(const char * format,...)294 static MD_INLINE void LogError(const char* format, ...)
295 {
296 va_list ap;
297 va_start(ap, format);
298 fprintf(stderr, "ERROR: ");
299 vfprintf(stderr, format, ap);
300 fprintf(stderr, "\n");
301 va_end(ap);
302 }
LogWarning(const char * format,...)303 static MD_INLINE void LogWarning(const char* format, ...)
304 {
305 va_list ap;
306 va_start(ap, format);
307 fprintf(stderr, "WARNING: ");
308 vfprintf(stderr, format, ap);
309 fprintf(stderr, "\n");
310 va_end(ap);
311 }
LogInfo(const char * format,...)312 static MD_INLINE void LogInfo(const char* format, ...)
313 {
314 va_list ap;
315 va_start(ap, format);
316 vfprintf(stderr, format, ap);
317 fprintf(stderr, "\n");
318 va_end(ap);
319 }
320
TRACE_ERROR(const char * format,...)321 static MD_INLINE void TRACE_ERROR(const char* format, ...)
322 {
323 #ifndef NDEBUG
324 va_list ap;
325 va_start(ap, format);
326 fprintf(stderr, "TRACE: ERROR: ");
327 vfprintf(stderr, format, ap);
328 fprintf(stderr, "\n");
329 va_end(ap);
330 #else
331 MD_VAR_NOT_USED(format);
332 #endif /* NDEBUG */
333 }
334
TRACE_WARNING(const char * format,...)335 static MD_INLINE void TRACE_WARNING(const char* format, ...)
336 {
337 #ifndef NDEBUG
338 va_list ap;
339 va_start(ap, format);
340 fprintf(stderr, "TRACE: WARNING: ");
341 vfprintf(stderr, format, ap);
342 fprintf(stderr, "\n");
343 va_end(ap);
344 #else
345 MD_VAR_NOT_USED(format);
346 #endif /* NDEBUG */
347 }
348
TRACE_INFO(const char * format,...)349 static MD_INLINE void TRACE_INFO(const char* format, ...)
350 {
351 #ifndef NDEBUG
352 va_list ap;
353 va_start(ap, format);
354 fprintf(stderr, "TRACE: ");
355 vfprintf(stderr, format, ap);
356 fprintf(stderr, "\n");
357 va_end(ap);
358 #else
359 MD_VAR_NOT_USED(format);
360 #endif /* NDEBUG */
361 }
362 #endif /* defined(LINUX) || defined(__ANDROID32__) */
363
364 /*----------------------------------------------------------------------------
365 * Globals
366 *----------------------------------------------------------------------------*/
367 /* The sector size */
368 static uint32_t g_nSectorSize;
369
370 /* The workspace size */
371 static uint32_t g_nWorkspaceSize = DEFAULT_WORKSPACE_SIZE;
372
373 /* UUID of the delegation service */
374 static const TEEC_UUID g_sServiceId = SERVICE_DELEGATION_UUID;
375
376 /* pWorkspaceBuffer points to the workspace buffer shared with the secure
377 world to transfer the sectors in the READ and WRITE instructions */
378 static uint8_t* g_pWorkspaceBuffer;
379 static DELEGATION_EXCHANGE_BUFFER * g_pExchangeBuffer;
380 TEEC_SharedMemory sExchangeSharedMem;
381 /*
382 The absolute path name for each of the 16 possible partitions.
383 */
384 static char* g_pPartitionNames[16];
385
386 /* The file context for each of the 16 possible partitions. An entry
387 in this array is NULL if the corresponding partition is currently not opened
388 */
389 static FILE* g_pPartitionFiles[16];
390
391 /*----------------------------------------------------------------------------
392 * Utilities functions
393 *----------------------------------------------------------------------------*/
printUsage(void)394 static void printUsage(void)
395 {
396 LogInfo("usage : tf_daemon [options]");
397 LogInfo("where [options] are:");
398 LogInfo("-h --help Display help.");
399 #ifdef SUPPORT_DELEGATION_EXTENSION
400 LogInfo("-c <conf> Configuration file path.");
401 #else
402 /* If the compilation parameter SUPPORT_DELEGATION_EXTENSION is not set, each
403 partition is stored as a file within the base dir */
404 LogInfo("-storageDir <baseDir> Set the directory where the data will be stored; this directory");
405 LogInfo(" must be writable and executable (this parameter is mandatory)");
406 #endif
407 LogInfo("-d Turns on debug mode. If not specified, the daemon will fork itself");
408 LogInfo(" and get detached from the console.");
409 #ifndef SUPPORT_DELEGATION_EXTENSION
410 LogInfo("-workspaceSize <integer> Set the size in bytes of the workspace. Must be greater or equal to 8 sectors.");
411 LogInfo(" (default is 128KB)");
412 #endif
413 }
414
errno2serror(void)415 static TEEC_Result errno2serror(void)
416 {
417 switch (errno)
418 {
419 case EINVAL:
420 return S_ERROR_BAD_PARAMETERS;
421 case EMFILE:
422 return S_ERROR_NO_MORE_HANDLES;
423 case ENOENT:
424 return S_ERROR_ITEM_NOT_FOUND;
425 case EEXIST:
426 return S_ERROR_ITEM_EXISTS;
427 case ENOSPC:
428 return S_ERROR_STORAGE_NO_SPACE;
429 case ENOMEM:
430 return S_ERROR_OUT_OF_MEMORY;
431 case EBADF:
432 case EACCES:
433 default:
434 return S_ERROR_STORAGE_UNREACHABLE;
435 }
436 }
437
438 /*
439 * Check if the directory in parameter exists with Read/Write access
440 * Return 0 in case of success and 1 otherwise.
441 */
static_checkStorageDirAndAccessRights(char * directoryName)442 int static_checkStorageDirAndAccessRights(char * directoryName)
443 {
444 #ifdef __SYMBIAN32__
445 /* it looks like stat is not working properly on Symbian
446 Create and remove dummy file to check access rights */
447 FILE *stream;
448 char *checkAccess = NULL;
449
450 if (directoryName == NULL)
451 {
452 LogError("Directory Name is NULL");
453 return 1;
454 }
455
456 checkAccess = malloc(strlen(directoryName)+1/* \ */ +1 /* a */ + 1 /* 0 */);
457 if (!checkAccess)
458 {
459 LogError("storageDir '%s' allocation error", directoryName);
460 return 1;
461 }
462 sprintf(checkAccess,"%s\\a",directoryName);
463 stream = fopen(checkAccess, "w+b");
464 if (!stream)
465 {
466 LogError("storageDir '%s' is incorrect or cannot be reached", directoryName);
467 return 1;
468 }
469 fclose(stream);
470 unlink(checkAccess);
471 #else
472 /* Non-Symbian OS: use stat */
473 struct stat buf;
474 int result = 0;
475
476 if (directoryName == NULL)
477 {
478 LogError("Directory Name is NULL");
479 return 1;
480 }
481
482 result = stat(directoryName, &buf);
483 if (result == 0)
484 {
485 /* Storage dir exists. Check access rights */
486 #if defined(LINUX) || (defined __ANDROID32__)
487 if ((buf.st_mode & (S_IXUSR | S_IWUSR)) != (S_IXUSR | S_IWUSR))
488 {
489 LogError("storageDir '%s' does not have read-write access", directoryName);
490 return 1;
491 }
492 #endif
493 }
494 else if (errno == ENOENT)
495 {
496 LogError("storageDir '%s' does not exist", directoryName);
497 return 1;
498 }
499 else
500 {
501 /* Another error */
502 LogError("storageDir '%s' is incorrect or cannot be reached", directoryName);
503 return 1;
504 }
505 #endif
506 return 0;
507 }
508
509
510
511 /*----------------------------------------------------------------------------
512 * Instructions
513 *----------------------------------------------------------------------------*/
514
515 /**
516 * This function executes the DESTROY_PARTITION instruction
517 *
518 * @param nPartitionID: the partition identifier
519 **/
partitionDestroy(uint32_t nPartitionID)520 static TEEC_Result partitionDestroy(uint32_t nPartitionID)
521 {
522 TEEC_Result nError = S_SUCCESS;
523
524 if (g_pPartitionFiles[nPartitionID] != NULL)
525 {
526 /* The partition must not be currently opened */
527 LogError("g_pPartitionFiles not NULL");
528 return S_ERROR_BAD_STATE;
529 }
530
531 /* Try to erase the file */
532 #if defined(LINUX) || (defined __ANDROID32__) || defined (__SYMBIAN32__)
533 if (unlink(g_pPartitionNames[nPartitionID]) != 0)
534 #endif
535 #ifdef WIN32
536 if (_unlink(g_pPartitionNames[nPartitionID]) != 0)
537 #endif
538 {
539 /* File in use or OS didn't allow the operation */
540 nError = errno2serror();
541 }
542
543 return nError;
544 }
545
546 /**
547 * This function executes the CREATE_PARTITION instruction. When successful,
548 * it fills the g_pPartitionFiles[nPartitionID] slot.
549 *
550 * @param nPartitionID: the partition identifier
551 **/
partitionCreate(uint32_t nPartitionID)552 static TEEC_Result partitionCreate(uint32_t nPartitionID)
553 {
554 uint32_t nError = S_SUCCESS;
555
556 if (g_pPartitionFiles[nPartitionID] != NULL)
557 {
558 /* The partition is already opened */
559 LogError("g_pPartitionFiles not NULL");
560 return S_ERROR_BAD_STATE;
561 }
562
563 /* Create the file unconditionnally */
564 LogInfo("Create storage file \"%s\"", g_pPartitionNames[nPartitionID]);
565 g_pPartitionFiles[nPartitionID] = fopen(g_pPartitionNames[nPartitionID], "w+b");
566
567 if (g_pPartitionFiles[nPartitionID] == NULL)
568 {
569 LogError("Cannot create storage file \"%s\"", g_pPartitionNames[nPartitionID]);
570 nError = errno2serror();
571 return nError;
572 }
573
574 return nError;
575 }
576
577 /**
578 * This function executes the OPEN_PARTITION instruction. When successful,
579 * it fills the g_pPartitionFiles[nPartitionID] slot and writes the partition
580 * size in hResultEncoder
581 *
582 * @param nPartitionID: the partition identifier
583 * @param pnPartitionSize: filled with the number of sectors in the partition
584 **/
partitionOpen(uint32_t nPartitionID,uint32_t * pnPartitionSize)585 static TEEC_Result partitionOpen(uint32_t nPartitionID, uint32_t* pnPartitionSize)
586 {
587 uint32_t nError = S_SUCCESS;
588
589 if (g_pPartitionFiles[nPartitionID] != NULL)
590 {
591 /* No partition must be currently opened in the session */
592 LogError("g_pPartitionFiles not NULL");
593 return S_ERROR_BAD_STATE;
594 }
595
596 /* Open the file */
597 g_pPartitionFiles[nPartitionID] = fopen(g_pPartitionNames[nPartitionID], "r+b");
598 if (g_pPartitionFiles[nPartitionID] == NULL)
599 {
600 if (errno == ENOENT)
601 {
602 /* File does not exist */
603 LogError("Storage file \"%s\" does not exist", g_pPartitionNames[nPartitionID]);
604 nError = S_ERROR_ITEM_NOT_FOUND;
605 return nError;
606 }
607 else
608 {
609 LogError("cannot open storage file \"%s\"", g_pPartitionNames[nPartitionID]);
610 nError = errno2serror();
611 return nError;
612 }
613 }
614 /* Determine the current number of sectors */
615 fseek(g_pPartitionFiles[nPartitionID], 0L, SEEK_END);
616 *pnPartitionSize = ftell(g_pPartitionFiles[nPartitionID]) / g_nSectorSize;
617
618 LogInfo("storage file \"%s\" successfully opened (size = %d KB (%d bytes))",
619 g_pPartitionNames[nPartitionID],
620 ((*pnPartitionSize) * g_nSectorSize) / 1024,
621 ((*pnPartitionSize) * g_nSectorSize));
622
623 return nError;
624 }
625
626
627 /**
628 * This function executes the CLOSE_PARTITION instruction.
629 * It closes the partition file.
630 *
631 * @param nPartitionID: the partition identifier
632 **/
partitionClose(uint32_t nPartitionID)633 static TEEC_Result partitionClose(uint32_t nPartitionID)
634 {
635 if (g_pPartitionFiles[nPartitionID] == NULL)
636 {
637 /* The partition is currently not opened */
638 return S_ERROR_BAD_STATE;
639 }
640 fclose(g_pPartitionFiles[nPartitionID]);
641 g_pPartitionFiles[nPartitionID] = NULL;
642 return S_SUCCESS;
643 }
644
645 /**
646 * This function executes the READ instruction.
647 *
648 * @param nPartitionID: the partition identifier
649 * @param nSectorIndex: the index of the sector to read
650 * @param nWorkspaceOffset: the offset in the workspace where the sector must be written
651 **/
partitionRead(uint32_t nPartitionID,uint32_t nSectorIndex,uint32_t nWorkspaceOffset)652 static TEEC_Result partitionRead(uint32_t nPartitionID, uint32_t nSectorIndex, uint32_t nWorkspaceOffset)
653 {
654 FILE* pFile;
655
656 TRACE_INFO(">Partition %1X: read sector 0x%08X into workspace at offset 0x%08X",
657 nPartitionID, nSectorIndex, nWorkspaceOffset);
658
659 pFile = g_pPartitionFiles[nPartitionID];
660
661 if (pFile == NULL)
662 {
663 /* The partition is not opened */
664 return S_ERROR_BAD_STATE;
665 }
666
667 if (fseek(pFile, nSectorIndex*g_nSectorSize, SEEK_SET) != 0)
668 {
669 LogError("fseek error: %s", strerror(errno));
670 return errno2serror();
671 }
672
673 if (fread(g_pWorkspaceBuffer + nWorkspaceOffset,
674 g_nSectorSize, 1,
675 pFile) != 1)
676 {
677 if (feof(pFile))
678 {
679 LogError("fread error: End-Of-File detected");
680 return S_ERROR_ITEM_NOT_FOUND;
681 }
682 LogError("fread error: %s", strerror(errno));
683 return errno2serror();
684 }
685
686 return S_SUCCESS;
687 }
688
689 /**
690 * This function executes the WRITE instruction.
691 *
692 * @param nPartitionID: the partition identifier
693 * @param nSectorIndex: the index of the sector to read
694 * @param nWorkspaceOffset: the offset in the workspace where the sector must be read
695 **/
partitionWrite(uint32_t nPartitionID,uint32_t nSectorIndex,uint32_t nWorkspaceOffset)696 static TEEC_Result partitionWrite(uint32_t nPartitionID, uint32_t nSectorIndex, uint32_t nWorkspaceOffset)
697 {
698 FILE* pFile;
699
700 TRACE_INFO(">Partition %1X: write sector 0x%X from workspace at offset 0x%X",
701 nPartitionID, nSectorIndex, nWorkspaceOffset);
702
703 pFile = g_pPartitionFiles[nPartitionID];
704
705 if (pFile == NULL)
706 {
707 /* The partition is not opened */
708 return S_ERROR_BAD_STATE;
709 }
710
711 if (fseek(pFile, nSectorIndex*g_nSectorSize, SEEK_SET) != 0)
712 {
713 LogError("fseek error: %s", strerror(errno));
714 return errno2serror();
715 }
716
717 if (fwrite(g_pWorkspaceBuffer + nWorkspaceOffset,
718 g_nSectorSize, 1,
719 pFile) != 1)
720 {
721 LogError("fread error: %s", strerror(errno));
722 return errno2serror();
723 }
724 return S_SUCCESS;
725 }
726
727
728 /**
729 * This function executes the SET_SIZE instruction.
730 *
731 * @param nPartitionID: the partition identifier
732 * @param nNewSectorCount: the new sector count
733 **/
partitionSetSize(uint32_t nPartitionID,uint32_t nNewSectorCount)734 static TEEC_Result partitionSetSize(uint32_t nPartitionID, uint32_t nNewSectorCount)
735 {
736 FILE* pFile;
737 uint32_t nCurrentSectorCount;
738
739 pFile = g_pPartitionFiles[nPartitionID];
740
741 if (pFile==NULL)
742 {
743 /* The partition is not opened */
744 return S_ERROR_BAD_STATE;
745 }
746
747 /* Determine the current size of the partition */
748 if (fseek(pFile, 0, SEEK_END) != 0)
749 {
750 LogError("fseek error: %s", strerror(errno));
751 return errno2serror();
752 }
753 nCurrentSectorCount = ftell(pFile) / g_nSectorSize;
754
755 if (nNewSectorCount > nCurrentSectorCount)
756 {
757 uint32_t nAddedBytesCount;
758 /* Enlarge the partition file. Make sure we actually write
759 some non-zero data into the new sectors. Otherwise, some file-system
760 might not really reserve the storage space but use a
761 sparse representation. In this case, a subsequent write instruction
762 could fail due to out-of-space, which we want to avoid. */
763 nAddedBytesCount = (nNewSectorCount-nCurrentSectorCount)*g_nSectorSize;
764 while (nAddedBytesCount)
765 {
766 if (fputc(0xA5, pFile)!=0xA5)
767 {
768 return errno2serror();
769 }
770 nAddedBytesCount--;
771 }
772 }
773 else if (nNewSectorCount < nCurrentSectorCount)
774 {
775 int result = 0;
776 /* Truncate the partition file */
777 #if defined(LINUX) || (defined __ANDROID32__)
778 result = ftruncate(fileno(pFile),nNewSectorCount * g_nSectorSize);
779 #endif
780 #if defined (__SYMBIAN32__)
781 LogError("No truncate available in Symbian C API");
782 #endif
783 #ifdef WIN32
784 result = _chsize(_fileno(pFile),nNewSectorCount * g_nSectorSize);
785 #endif
786 if (result)
787 {
788 return errno2serror();
789 }
790 }
791 return S_SUCCESS;
792 }
793
794 /**
795 * This function executes the SYNC instruction.
796 *
797 * @param pPartitionID: the partition identifier
798 **/
partitionSync(uint32_t nPartitionID)799 static TEEC_Result partitionSync(uint32_t nPartitionID)
800 {
801 TEEC_Result nError = S_SUCCESS;
802 int result;
803
804 FILE* pFile = g_pPartitionFiles[nPartitionID];
805
806 if (pFile == NULL)
807 {
808 /* The partition is not currently opened */
809 return S_ERROR_BAD_STATE;
810 }
811
812 /* First make sure that the data in the stdio buffers
813 is flushed to the file descriptor */
814 result=fflush(pFile);
815 if (result)
816 {
817 nError=errno2serror();
818 goto end;
819 }
820 /* Then synchronize the file descriptor with the file-system */
821
822 #if defined(LINUX) || (defined __ANDROID32__)
823 result=fdatasync(fileno(pFile));
824 #endif
825 #if defined (__SYMBIAN32__)
826 result=fsync(fileno(pFile));
827 #endif
828 #ifdef WIN32
829 result=_commit(_fileno(pFile));
830 #endif
831 if (result)
832 {
833 nError=errno2serror();
834 }
835
836 end:
837 return nError;
838 }
839
840 /**
841 * This function executes the NOTIFY instruction.
842 *
843 * @param pMessage the message string
844 * @param nMessageType the type of messages
845 **/
notify(const wchar_t * pMessage,uint32_t nMessageType)846 static void notify(const wchar_t* pMessage, uint32_t nMessageType)
847 {
848 switch (nMessageType)
849 {
850 case DELEGATION_NOTIFY_TYPE_ERROR:
851 LogError("%ls", pMessage);
852 break;
853 case DELEGATION_NOTIFY_TYPE_WARNING:
854 LogWarning("%ls", pMessage);
855 break;
856 case DELEGATION_NOTIFY_TYPE_DEBUG:
857 LogInfo("DEBUG: %ls", pMessage);
858 break;
859 case DELEGATION_NOTIFY_TYPE_INFO:
860 default:
861 LogInfo("%ls", pMessage);
862 break;
863 }
864 }
865
866 /*----------------------------------------------------------------------------
867 * Session main function
868 *----------------------------------------------------------------------------*/
869
870 /*
871 * This function runs a session opened on the delegation service. It fetches
872 * instructions and execute them in a loop. It never returns, but may call
873 * exit when instructed to shutdown by the service
874 */
runSession(TEEC_Context * pContext,TEEC_Session * pSession,TEEC_Operation * pOperation)875 static int runSession(TEEC_Context* pContext, TEEC_Session* pSession, TEEC_Operation* pOperation)
876 {
877 memset(&g_pExchangeBuffer->sAdministrativeData, 0x00, sizeof(g_pExchangeBuffer->sAdministrativeData));
878
879 while (true)
880 {
881 S_RESULT nError;
882 TEEC_Result nTeeError;
883 uint32_t nInstructionsIndex;
884 uint32_t nInstructionsBufferSize = sizeof(g_pExchangeBuffer->sInstructions);
885
886 pOperation->paramTypes = TEEC_PARAM_TYPES(
887 TEEC_MEMREF_PARTIAL_INPUT,
888 TEEC_MEMREF_PARTIAL_OUTPUT,
889 TEEC_MEMREF_PARTIAL_INOUT,
890 TEEC_NONE);
891 pOperation->params[0].memref.parent = &sExchangeSharedMem;
892 pOperation->params[0].memref.offset = offsetof(DELEGATION_EXCHANGE_BUFFER, sAdministrativeData);
893 pOperation->params[0].memref.size = sizeof(g_pExchangeBuffer->sAdministrativeData);
894
895 pOperation->params[1].memref.parent = &sExchangeSharedMem;
896 pOperation->params[1].memref.offset = offsetof(DELEGATION_EXCHANGE_BUFFER, sInstructions);
897 pOperation->params[1].memref.size = sizeof(g_pExchangeBuffer->sInstructions);
898
899 pOperation->params[2].memref.parent = &sExchangeSharedMem;
900 pOperation->params[2].memref.offset = offsetof(DELEGATION_EXCHANGE_BUFFER, sWorkspace);
901 pOperation->params[2].memref.size = g_nWorkspaceSize;
902
903 nTeeError = TEEC_InvokeCommand(pSession,
904 SERVICE_DELEGATION_GET_INSTRUCTIONS, /* commandID */
905 pOperation, /* IN OUT operation */
906 NULL /* OUT errorOrigin, optional */
907 );
908
909 if (nTeeError != TEEC_SUCCESS)
910 {
911 LogError("TEEC_InvokeCommand error: 0x%08X", nTeeError);
912 LogError("Daemon exits");
913 exit(2);
914 }
915
916 if (pOperation->params[1].tmpref.size > nInstructionsBufferSize)
917 {
918 /* Should not happen, probably an error from the service */
919 pOperation->params[1].tmpref.size = 0;
920 }
921
922 /* Reset the operation results */
923 nError = TEEC_SUCCESS;
924 g_pExchangeBuffer->sAdministrativeData.nSyncExecuted = 0;
925 memset(g_pExchangeBuffer->sAdministrativeData.nPartitionErrorStates, 0x00, sizeof(g_pExchangeBuffer->sAdministrativeData.nPartitionErrorStates));
926 memset(g_pExchangeBuffer->sAdministrativeData.nPartitionOpenSizes, 0x00, sizeof(g_pExchangeBuffer->sAdministrativeData.nPartitionOpenSizes));
927
928 /* Execute the instructions */
929 nInstructionsIndex = 0;
930 nInstructionsBufferSize = pOperation->params[1].tmpref.size;
931 while (true)
932 {
933 DELEGATION_INSTRUCTION * pInstruction;
934 uint32_t nInstructionID;
935 pInstruction = (DELEGATION_INSTRUCTION *)(&g_pExchangeBuffer->sInstructions[nInstructionsIndex/4]);
936 if (nInstructionsIndex + 4 <= nInstructionsBufferSize)
937 {
938 nInstructionID = pInstruction->sGeneric.nInstructionID;
939 nInstructionsIndex+=4;
940 }
941 else
942 {
943 goto instruction_parse_end;
944 }
945 if ((nInstructionID & 0x0F) == 0)
946 {
947 /* Partition-independent instruction */
948 switch (nInstructionID)
949 {
950 case DELEGATION_INSTRUCTION_SHUTDOWN:
951 {
952 exit(0);
953 /* The implementation of the TF Client API will automatically
954 destroy the context and release any associated resource */
955 }
956 case DELEGATION_INSTRUCTION_NOTIFY:
957 {
958 /* Parse the instruction parameters */
959 wchar_t pMessage[100];
960 uint32_t nMessageType;
961 uint32_t nMessageSize;
962 memset(pMessage, 0, 100*sizeof(wchar_t));
963
964 if (nInstructionsIndex + 8 <= nInstructionsBufferSize)
965 {
966 nMessageType = pInstruction->sNotify.nMessageType;
967 nMessageSize = pInstruction->sNotify.nMessageSize;
968 nInstructionsIndex+=8;
969 }
970 else
971 {
972 goto instruction_parse_end;
973 }
974 if (nMessageSize > (99)*sizeof(wchar_t))
975 {
976 /* How to handle the error correctly in this case ? */
977 goto instruction_parse_end;
978 }
979 if (nInstructionsIndex + nMessageSize <= nInstructionsBufferSize)
980 {
981 memcpy(pMessage, &pInstruction->sNotify.nMessage[0], nMessageSize);
982 nInstructionsIndex+=nMessageSize;
983 }
984 else
985 {
986 goto instruction_parse_end;
987 }
988 /* Align the pInstructionsIndex on 4 bytes */
989 nInstructionsIndex = (nInstructionsIndex+3)&~3;
990 notify(pMessage, nMessageType);
991 break;
992 }
993 default:
994 LogError("Unknown instruction identifier: %02X", nInstructionID);
995 nError = S_ERROR_BAD_PARAMETERS;
996 break;
997 }
998 }
999 else
1000 {
1001 /* Partition-specific instruction */
1002 uint32_t nPartitionID = (nInstructionID & 0xF0) >> 4;
1003 if (g_pExchangeBuffer->sAdministrativeData.nPartitionErrorStates[nPartitionID] == S_SUCCESS)
1004 {
1005 /* Execute the instruction only if there is currently no
1006 error on the partition */
1007 switch (nInstructionID & 0x0F)
1008 {
1009 case DELEGATION_INSTRUCTION_PARTITION_CREATE:
1010 nError = partitionCreate(nPartitionID);
1011 TRACE_INFO("INSTRUCTION: ID=0x%x pid=%d err=%d", (nInstructionID & 0x0F), nPartitionID, nError);
1012 break;
1013 case DELEGATION_INSTRUCTION_PARTITION_OPEN:
1014 {
1015 uint32_t nPartitionSize = 0;
1016 nError = partitionOpen(nPartitionID, &nPartitionSize);
1017 TRACE_INFO("INSTRUCTION: ID=0x%x pid=%d pSize=%d err=%d", (nInstructionID & 0x0F), nPartitionID, nPartitionSize, nError);
1018 if (nError == S_SUCCESS)
1019 {
1020 g_pExchangeBuffer->sAdministrativeData.nPartitionOpenSizes[nPartitionID] = nPartitionSize;
1021 }
1022 break;
1023 }
1024 case DELEGATION_INSTRUCTION_PARTITION_READ:
1025 {
1026 /* Parse parameters */
1027 uint32_t nSectorID;
1028 uint32_t nWorkspaceOffset;
1029 if (nInstructionsIndex + 8 <= nInstructionsBufferSize)
1030 {
1031 nSectorID = pInstruction->sReadWrite.nSectorID;
1032 nWorkspaceOffset = pInstruction->sReadWrite.nWorkspaceOffset;
1033 nInstructionsIndex+=8;
1034 }
1035 else
1036 {
1037 goto instruction_parse_end;
1038 }
1039 nError = partitionRead(nPartitionID, nSectorID, nWorkspaceOffset);
1040 TRACE_INFO("INSTRUCTION: ID=0x%x pid=%d sid=%d woff=%d err=%d", (nInstructionID & 0x0F), nPartitionID, nSectorID, nWorkspaceOffset, nError);
1041 break;
1042 }
1043 case DELEGATION_INSTRUCTION_PARTITION_WRITE:
1044 {
1045 /* Parse parameters */
1046 uint32_t nSectorID;
1047 uint32_t nWorkspaceOffset;
1048 if (nInstructionsIndex + 8 <= nInstructionsBufferSize)
1049 {
1050 nSectorID = pInstruction->sReadWrite.nSectorID;
1051 nWorkspaceOffset = pInstruction->sReadWrite.nWorkspaceOffset;
1052 nInstructionsIndex+=8;
1053 }
1054 else
1055 {
1056 goto instruction_parse_end;
1057 }
1058 nError = partitionWrite(nPartitionID, nSectorID, nWorkspaceOffset);
1059 TRACE_INFO("INSTRUCTION: ID=0x%x pid=%d sid=%d woff=%d err=%d", (nInstructionID & 0x0F), nPartitionID, nSectorID, nWorkspaceOffset, nError);
1060 break;
1061 }
1062 case DELEGATION_INSTRUCTION_PARTITION_SYNC:
1063 nError = partitionSync(nPartitionID);
1064 TRACE_INFO("INSTRUCTION: ID=0x%x pid=%d err=%d", (nInstructionID & 0x0F), nPartitionID, nError);
1065 if (nError == S_SUCCESS)
1066 {
1067 g_pExchangeBuffer->sAdministrativeData.nSyncExecuted++;
1068 }
1069 break;
1070 case DELEGATION_INSTRUCTION_PARTITION_SET_SIZE:
1071 {
1072 uint32_t nNewSize;
1073 if (nInstructionsIndex + 4 <= nInstructionsBufferSize)
1074 {
1075 nNewSize = pInstruction->sSetSize.nNewSize;
1076 nInstructionsIndex+=4;
1077 }
1078 else
1079 {
1080 goto instruction_parse_end;
1081 }
1082 nError = partitionSetSize(nPartitionID, nNewSize);
1083 TRACE_INFO("INSTRUCTION: ID=0x%x pid=%d nNewSize=%d err=%d", (nInstructionID & 0x0F), nPartitionID, nNewSize, nError);
1084 break;
1085 }
1086 case DELEGATION_INSTRUCTION_PARTITION_CLOSE:
1087 nError = partitionClose(nPartitionID);
1088 TRACE_INFO("INSTRUCTION: ID=0x%x pid=%d err=%d", (nInstructionID & 0x0F), nPartitionID, nError);
1089 break;
1090 case DELEGATION_INSTRUCTION_PARTITION_DESTROY:
1091 nError = partitionDestroy(nPartitionID);
1092 TRACE_INFO("INSTRUCTION: ID=0x%x pid=%d err=%d", (nInstructionID & 0x0F), nPartitionID, nError);
1093 break;
1094 }
1095 g_pExchangeBuffer->sAdministrativeData.nPartitionErrorStates[nPartitionID] = nError;
1096 }
1097 }
1098 }
1099 instruction_parse_end:
1100 memset(pOperation, 0, sizeof(TEEC_Operation));
1101 }
1102 }
1103
1104 /**
1105 * This function opens a new session to the delegation service.
1106 **/
createSession(TEEC_Context * pContext,TEEC_Session * pSession,TEEC_Operation * pOperation)1107 static int createSession(TEEC_Context* pContext, TEEC_Session* pSession, TEEC_Operation* pOperation)
1108 {
1109 TEEC_Result nError;
1110 uint32_t nExchangeBufferSize;
1111
1112 memset(pOperation, 0, sizeof(TEEC_Operation));
1113 pOperation->paramTypes = TEEC_PARAM_TYPES(
1114 TEEC_VALUE_OUTPUT, TEEC_NONE, TEEC_NONE, TEEC_NONE);
1115 nError = TEEC_OpenSession(pContext,
1116 pSession, /* OUT session */
1117 &g_sServiceId, /* destination UUID */
1118 TEEC_LOGIN_PRIVILEGED, /* connectionMethod */
1119 NULL, /* connectionData */
1120 pOperation, /* IN OUT operation */
1121 NULL /* OUT errorOrigin, optional */
1122 );
1123 if (nError != TEEC_SUCCESS)
1124 {
1125 LogError("Error on TEEC_OpenSession : 0x%x", nError);
1126 exit(2);
1127 }
1128 /* Read sector size */
1129 g_nSectorSize = pOperation->params[0].value.a;
1130 LogInfo("Sector Size: %d bytes", g_nSectorSize);
1131
1132 /* Check sector size */
1133 if (!(g_nSectorSize == 512 || g_nSectorSize == 1024 || g_nSectorSize == 2048 || g_nSectorSize == 4096))
1134 {
1135 LogError("Incorrect sector size: terminating...");
1136 exit(2);
1137 }
1138
1139 /* Check workspace size */
1140 if (g_nWorkspaceSize < 8 * g_nSectorSize)
1141 {
1142 g_nWorkspaceSize = 8 * g_nSectorSize;
1143 LogWarning("Workspace size too small, automatically set to %d bytes", g_nWorkspaceSize);
1144 }
1145 /* Compute the size of the exchange buffer */
1146 nExchangeBufferSize = sizeof(DELEGATION_EXCHANGE_BUFFER)-1+g_nWorkspaceSize;
1147 g_pExchangeBuffer = (DELEGATION_EXCHANGE_BUFFER*)malloc(nExchangeBufferSize);
1148 if (g_pExchangeBuffer == NULL)
1149 {
1150 LogError("Cannot allocate exchange buffer of %d bytes", nExchangeBufferSize);
1151 LogError("Now exiting...");
1152 exit(2);
1153 }
1154 g_pWorkspaceBuffer = (uint8_t*)g_pExchangeBuffer->sWorkspace;
1155 memset(g_pExchangeBuffer, 0x00, nExchangeBufferSize);
1156 memset(g_pPartitionFiles,0,16*sizeof(FILE*));
1157
1158 /* Register the exchange buffer as a shared memory block */
1159 sExchangeSharedMem.buffer = g_pExchangeBuffer;
1160 sExchangeSharedMem.size = nExchangeBufferSize;
1161 sExchangeSharedMem.flags = TEEC_MEM_INPUT | TEEC_MEM_OUTPUT;
1162 nError = TEEC_RegisterSharedMemory(pContext, &sExchangeSharedMem);
1163 if (nError != TEEC_SUCCESS)
1164 {
1165 LogError("Error on TEEC_RegisterSharedMemory : 0x%x", nError);
1166 free(g_pExchangeBuffer);
1167 exit(2);
1168 }
1169 LogInfo("Daemon now connected");
1170 return 0;
1171 }
1172
1173
1174 /*----------------------------------------------------------------------------
1175 * Main
1176 *----------------------------------------------------------------------------*/
1177
1178 #ifdef INCLUDE_CLIENT_DELEGATION
delegation_main(int argc,char * argv[])1179 int delegation_main(int argc, char* argv[])
1180 #else
1181 int main(int argc, char* argv[])
1182 #endif
1183 {
1184 TEEC_Result nError;
1185 TEEC_Context sContext;
1186 TEEC_Session sSession;
1187 TEEC_Operation sOperation;
1188 bool debug = false;
1189
1190 #ifndef SUPPORT_DELEGATION_EXTENSION
1191 char * baseDir = NULL;
1192
1193 LogInfo("TFSW Normal-World Daemon");
1194 #else
1195 LogInfo("TFSW Normal-World Ext Daemon");
1196 #endif
1197 LogInfo(S_VERSION_STRING);
1198 LogInfo("");
1199
1200 /* Skip program name */
1201 argv++;
1202 argc--;
1203
1204 while (argc != 0)
1205 {
1206 if (strcmp(argv[0], "-d") == 0)
1207 {
1208 debug = true;
1209 }
1210 #ifdef SUPPORT_DELEGATION_EXTENSION
1211 else if (strcmp(argv[0], "-c") == 0)
1212 {
1213 int error;
1214 argc--;
1215 argv++;
1216 if (argc == 0)
1217 {
1218 printUsage();
1219 return 1;
1220 }
1221 /* Note that the function parseCommandLineExtension can modify the
1222 content of the g_partitionNames array */
1223 error = parseCommandLineExtension(argv[0], g_pPartitionNames);
1224 if ( error != 0 )
1225 {
1226 printUsage();
1227 return error;
1228 }
1229 }
1230 #else
1231 else if (strcmp(argv[0], "-storageDir") == 0)
1232 {
1233 uint32_t i = 0;
1234 argc--;
1235 argv++;
1236 if (argc == 0)
1237 {
1238 printUsage();
1239 return 1;
1240 }
1241 if (baseDir != NULL)
1242 {
1243 LogError("Only one storage directory may be specified");
1244 return 1;
1245 }
1246 baseDir = malloc(strlen(argv[0])+1); /* Zero-terminated string */
1247 if (baseDir == NULL)
1248 {
1249 LogError("Out of memory");
1250 return 2;
1251 }
1252
1253 strcpy(baseDir, argv[0]);
1254
1255 /* Set default names to the partitions */
1256 for ( i=0; i<16 ;i++ )
1257 {
1258 g_pPartitionNames[i] = NULL;
1259 g_pPartitionNames[i] = malloc(strlen(baseDir) + 1 /* separator */ + sizeof("Store_X.tf"));
1260 if (g_pPartitionNames[i] != NULL)
1261 {
1262 sprintf(g_pPartitionNames[i], "%s%cStore_%1X.tf", baseDir, PATH_SEPARATOR, i);
1263 }
1264 else
1265 {
1266 free(baseDir);
1267 i=0;
1268 while(g_pPartitionNames[i] != NULL) free(g_pPartitionNames[i++]);
1269 LogError("Out of memory");
1270 return 2;
1271 }
1272 }
1273 }
1274 else if (strcmp(argv[0], "-workspaceSize") == 0)
1275 {
1276 argc--;
1277 argv++;
1278 if (argc == 0)
1279 {
1280 printUsage();
1281 return 1;
1282 }
1283 g_nWorkspaceSize=atol(argv[0]);
1284 }
1285 #endif /* ! SUPPORT_DELEGATION_EXTENSION */
1286 /*****************************************/
1287 else if (strcmp(argv[0], "--help") == 0 || strcmp(argv[0], "-h") == 0)
1288 {
1289 printUsage();
1290 return 0;
1291 }
1292 else
1293 {
1294 printUsage();
1295 return 1;
1296 }
1297 argc--;
1298 argv++;
1299 }
1300
1301 #ifndef SUPPORT_DELEGATION_EXTENSION
1302 if (baseDir == NULL)
1303 {
1304 LogError("-storageDir option is mandatory");
1305 return 1;
1306 }
1307 else
1308 {
1309 if (static_checkStorageDirAndAccessRights(baseDir) != 0)
1310 {
1311 return 1;
1312 }
1313 }
1314 #endif /* #ifndef SUPPORT_DELEGATION_EXTENSION */
1315
1316 /*
1317 * Detach the daemon from the console
1318 */
1319
1320 #if defined(LINUX) || (defined __ANDROID32__)
1321 {
1322 /*
1323 * Turns this application into a daemon => fork off parent process, setup logging, ...
1324 */
1325
1326 /* Our process ID and Session ID */
1327 pid_t pid, sid;
1328
1329 if (!debug)
1330 {
1331 LogInfo("tf_daemon is detaching from console... Further traces go to syslog");
1332 /* Fork off the parent process */
1333 pid = fork();
1334 if (pid < 0)
1335 {
1336 LogError("daemon forking failed");
1337 return 1;
1338 }
1339
1340 if (pid > 0)
1341 {
1342 /* parent */
1343 return 0;
1344 }
1345 bDetached = true;
1346 }
1347
1348 /* Change the file mode mask */
1349 umask(0077);
1350
1351 if (!debug)
1352 {
1353 /* Open any logs here */
1354 openlog("tf_daemon", 0, LOG_DAEMON);
1355
1356 /* Detach from the console */
1357 sid = setsid();
1358 if (sid < 0)
1359 {
1360 /* Log the failure */
1361 LogError("daemon group creation failed");
1362 return 1;
1363 }
1364 /* Close out the standard file descriptors */
1365 close(STDIN_FILENO);
1366 close(STDOUT_FILENO);
1367 close(STDERR_FILENO);
1368 }
1369 }
1370 /* Change priority so that tf_driver.ko with no polling thread is faster */
1371 if (setpriority(PRIO_PROCESS, 0, 19)!=0)
1372 {
1373 LogError("Daemon cannot change priority");
1374 return 1;
1375 }
1376
1377 #endif
1378
1379 TRACE_INFO("Sector size is %d", g_nSectorSize);
1380
1381 LogInfo("tf_daemon - started");
1382
1383 nError = TEEC_InitializeContext(NULL, /* const char * name */
1384 &sContext); /* TEEC_Context* context */
1385 if (nError != TEEC_SUCCESS)
1386 {
1387 LogError("TEEC_InitializeContext error: 0x%08X", nError);
1388 LogError("Now exiting...");
1389 exit(2);
1390 }
1391
1392 /* Open a session */
1393 if(createSession(&sContext, &sSession, &sOperation) == 0)
1394 {
1395 /* Run the session. This should never return */
1396 runSession(&sContext, &sSession, &sOperation);
1397 }
1398 TEEC_FinalizeContext(&sContext);
1399
1400 return 3;
1401 }
1402