Properly free previously allocated file path string and other minor cleanup
[ipc/ipcdev.git] / qnx / src / ipc3x_dev / ti / syslink / build / Qnx / resmgr / syslink_main.c
1 /*
2  *  @file       syslink_main.c
3  *
4  *  @brief      syslink main
5  *
6  *
7  *  @ver        02.00.00.46_alpha1
8  *
9  *  ============================================================================
10  *
11  *  Copyright (c) 2011-2014, Texas Instruments Incorporated
12  *
13  *  Redistribution and use in source and binary forms, with or without
14  *  modification, are permitted provided that the following conditions
15  *  are met:
16  *
17  *  *  Redistributions of source code must retain the above copyright
18  *     notice, this list of conditions and the following disclaimer.
19  *
20  *  *  Redistributions in binary form must reproduce the above copyright
21  *     notice, this list of conditions and the following disclaimer in the
22  *     documentation and/or other materials provided with the distribution.
23  *
24  *  *  Neither the name of Texas Instruments Incorporated nor the names of
25  *     its contributors may be used to endorse or promote products derived
26  *     from this software without specific prior written permission.
27  *
28  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
29  *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
30  *  THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
31  *  PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
32  *  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
33  *  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
34  *  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
35  *  OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
36  *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
37  *  OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
38  *  EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
39  *  Contact information for paper mail:
40  *  Texas Instruments
41  *  Post Office Box 655303
42  *  Dallas, Texas 75265
43  *  Contact information:
44  *  http://www-k.ext.ti.com/sc/technical-support/product-information-centers.htm?
45  *  DCMP=TIHomeTracking&HQS=Other+OT+home_d_contact
46  *  ============================================================================
47  *
48  */
50 #include "proto.h"
52 #include <pthread.h>
53 #include <fcntl.h>
54 #include <stdint.h>
55 #include <sys/procmgr.h>
56 #include <sys/neutrino.h>
57 #include <sys/siginfo.h>
58 #include <signal.h>
59 #include <stdbool.h>
61 #include <IpcKnl.h>
63 /* OSAL & Utils headers */
64 #include <ti/syslink/utils/List.h>
65 #include <ti/syslink/utils/MemoryOS.h>
66 #include <ti/ipc/MultiProc.h>
67 #include <ti/ipc/NameServer.h>
68 #include <_MultiProc.h>
69 #include <_NameServer.h>
70 #include <_GateMP_daemon.h>
71 #include <OsalSemaphore.h>
72 #include <ti/syslink/utils/OsalPrint.h>
73 #if defined(SYSLINK_PLATFORM_OMAP5430)
74 #include <_ipu_pm.h>
75 #endif
76 #include <ti/syslink/utils/Trace.h>
77 #include <ti/syslink/ProcMgr.h>
78 #include <Bitops.h>
79 #include <RscTable.h>
81 #include <ti-ipc.h>
83 #define DENY_ALL                    \
84             PROCMGR_ADN_ROOT        \
85             | PROCMGR_ADN_NONROOT   \
86             | PROCMGR_AOP_DENY      \
87             | PROCMGR_AOP_LOCK
90 static int verbosity = 2;
92 /* Disable recovery mechanism if true */
93 static int disableRecovery = false;
94 static char * logFilename = NULL;
96 /* Number of cores to attach to */
97 static int numAttach = 0;
99 #if defined(SYSLINK_PLATFORM_VAYU)
100 /* DSP2 is invalid on Vayu */
101 #define INVALID_PROC     "DSP2"
103 static bool gatempEnabled = false;
104 static Int32 sr0OwnerProcId = -1;
105 #else
106 #define INVALID_PROC     ""
107 #endif
109 // Syslink hibernation global variables
110 Bool syslink_hib_enable = TRUE;
111 #if !defined(SYSLINK_PLATFORM_OMAP5430)
112 #define PM_HIB_DEFAULT_TIME 5000
113 #endif
114 uint32_t syslink_hib_timeout = PM_HIB_DEFAULT_TIME;
115 Bool syslink_hib_hibernating = FALSE;
116 pthread_mutex_t syslink_hib_mutex = PTHREAD_MUTEX_INITIALIZER;
117 pthread_cond_t syslink_hib_cond = PTHREAD_COND_INITIALIZER;
119 extern Int rpmsg_rpc_setup (Void);
120 extern Void rpmsg_rpc_destroy (Void);
121 extern Void GateHWSpinlock_LeaveLockForPID(int pid);
123 typedef struct syslink_firmware_info_t {
124     uint16_t proc_id;
125     char * proc;
126     char * firmware;
127     bool attachOnly;
128     int  procState;  /* state of processor - index into procStateNames array */
129     int  readProcState; /* state that is currently being printed */
130     bool reload;     /* reload core during recovery */
131     bool freeString; /* Need to free previously allocated firmware string */
132 } syslink_firmware_info;
133 static syslink_firmware_info syslink_firmware[MultiProc_MAXPROCESSORS];
135 /* Number of valid entries in syslink_firmware array */
136 static unsigned int syslink_num_cores = 0;
138 int init_ipc(syslink_dev_t * dev, syslink_firmware_info * firmware,
139     bool recover);
140 int deinit_ipc(syslink_dev_t * dev, syslink_firmware_info * firmware,
141     bool recover);
142 int init_syslink_trace_device(syslink_dev_t *dev);
143 int deinit_syslink_trace_device(syslink_dev_t *dev);
145 Int syslink_error_cb (UInt16 procId, ProcMgr_Handle handle,
146                       ProcMgr_State fromState, ProcMgr_State toState,
147                       ProcMgr_EventStatus status, Ptr args);
149 static RscTable_Handle rscHandle[MultiProc_MAXPROCESSORS];
151 static ProcMgr_Handle procH[MultiProc_MAXPROCESSORS];
152 static unsigned int procH_fileId[MultiProc_MAXPROCESSORS];
153 static ProcMgr_State errStates[] = {ProcMgr_State_Mmu_Fault,
154                                     ProcMgr_State_Error,
155                                     ProcMgr_State_Watchdog,
156                                     ProcMgr_State_EndValue};
158 /* Processor states */
159 #define RESET_STATE  0
160 #define RUNNING_STATE 1
162 static String procStateNames[] = { "In reset\n",
163                                    "Running\n" };
165 typedef struct syslink_trace_info_t {
166     uintptr_t   va;
167     uint32_t    len;
168     uint32_t *  widx;
169     uint32_t *  ridx;
170     Bool        firstRead;
171 } syslink_trace_info;
173 static syslink_trace_info proc_traces[MultiProc_MAXPROCESSORS];
175 static int runSlave(syslink_dev_t *dev, uint16_t procId,
176     syslink_firmware_info * firmware_info)
178     int status = 0;
179     ProcMgr_AttachParams attachParams;
181     if (firmware_info->firmware) {
182         rscHandle[procId] = RscTable_alloc(firmware_info->firmware, procId);
183         if (rscHandle[procId] == NULL) {
184             status = -1;
185             return status;
186         }
187     }
189     status = ProcMgr_open(&procH[procId], procId);
190     if (status < 0 || procH[procId] == NULL) {
191         goto procmgropen_fail;
192     }
194     /* Load and start the remote processor. */
195     ProcMgr_getAttachParams(procH[procId], &attachParams);
196     if (firmware_info->attachOnly) {
197         attachParams.bootMode = ProcMgr_BootMode_NoBoot;
198     }
199     status = ProcMgr_attach(procH[procId], &attachParams);
200     if (status < 0) {
201         GT_setFailureReason(curTrace,
202                             GT_4CLASS,
203                             "runSlave",
204                             status,
205                             "ProcMgr_attach failed!");
206         goto procmgrattach_fail;
207     }
209     if ((firmware_info->firmware) &&
210         (!firmware_info->attachOnly)) {
211         status = ProcMgr_load(procH[procId],
212             (String)firmware_info->firmware, 0, NULL,
213              NULL, &procH_fileId[procId]);
214         if (status < 0) {
215             GT_setFailureReason(curTrace,
216                                 GT_4CLASS,
217                                 "runSlave",
218                                 status,
219                                 "ProcMgr_load failed!");
220             goto procmgrload_fail;
221         }
222     }
224     status = Ipc_attach(procId);
225     if (status < 0) {
226         GT_setFailureReason(curTrace,
227                              GT_4CLASS,
228                              "runSlave",
229                              status,
230                              "Ipc_attach failed!");
231         goto ipcattach_fail;
232     }
234     status = ProcMgr_registerNotify(procH[procId], syslink_error_cb, (Ptr)dev,
235         -1, errStates);
236     if (status < 0) {
237         goto procmgrreg_fail;
238     }
240     if (!firmware_info->attachOnly) {
241         status = ProcMgr_start(procH[procId], NULL);
242         if (status < 0) {
243             GT_setFailureReason(curTrace,
244                                 GT_4CLASS,
245                                 "runSlave",
246                                 status,
247                                 "ProcMgr_start failed!");
248             goto procmgrstart_fail;
249         }
250     }
252     Osal_printf("runSlave successful for core %d\n", procId);
254     return 0;
256 procmgrstart_fail:
257     ProcMgr_unregisterNotify(procH[procId], syslink_error_cb,
258         (Ptr)dev, errStates);
259 procmgrreg_fail:
260     Ipc_detach(procId);
261 ipcattach_fail:
262     if ((firmware_info->firmware) &&
263         (!firmware_info->attachOnly)) {
264         ProcMgr_unload(procH[procId], procH_fileId[procId]);
265     }
266 procmgrload_fail:
267     ProcMgr_detach(procH[procId]);
268 procmgrattach_fail:
269     ProcMgr_close(&procH[procId]);
270     procH[procId] = NULL;
271 procmgropen_fail:
272     RscTable_free(&rscHandle[procId]);
274     return -1;
277 static int resetSlave(syslink_dev_t *dev, uint16_t procId)
279     if ((procH[procId]) && (procH_fileId[procId])) {
280         GT_1trace(curTrace, GT_4CLASS, "stopping %s", MultiProc_getName(procId));
281         ProcMgr_stop(procH[procId]);
282     }
284     if (procH[procId]) {
285         ProcMgr_unregisterNotify(procH[procId], syslink_error_cb, (Ptr)dev,
286             errStates);
287         Ipc_detach(procId);
288         if (procH_fileId[procId]) {
289             ProcMgr_unload(procH[procId], procH_fileId[procId]);
290             procH_fileId[procId] = 0;
291         }
292         ProcMgr_detach(procH[procId]);
293         ProcMgr_close(&procH[procId]);
294         procH[procId] = NULL;
295         RscTable_free(&rscHandle[procId]);
296         rscHandle[procId] = NULL;
297     }
299     Osal_printf("resetSlave successful for core %d\n", procId);
301     return 0;
304 /* Add firmware entry after IPC is setup */
305 static void addFirmware(uint16_t procId)
307     syslink_firmware[syslink_num_cores].proc =
308         MultiProc_getName(procId);
309     syslink_firmware[syslink_num_cores].proc_id = procId;
310     syslink_firmware[syslink_num_cores].attachOnly = false;
311     syslink_firmware[syslink_num_cores].reload = false;
312     syslink_firmware[syslink_num_cores].procState = RESET_STATE;
313     syslink_firmware[syslink_num_cores].freeString = false;
314     syslink_firmware[syslink_num_cores++].firmware = NULL;
316     return;
319 static int slave_state_read(resmgr_context_t *ctp, io_read_t *msg,
320     syslink_ocb_t *ocb)
322     int             nbytes;
323     int             nparts;
324     int             status;
325     int             nleft;
326     int             i;
327     uint16_t        procId = ocb->ocb.attr->procid;
328     syslink_dev_t * dev = ocb->ocb.attr->dev;
330     if ((status = iofunc_read_verify(ctp, msg, &ocb->ocb, NULL)) != EOK) {
331         return (status);
332     }
334     if ((msg->i.xtype & _IO_XTYPE_MASK) != _IO_XTYPE_NONE) {
335         return (ENOSYS);
336     }
338     if (strcmp(MultiProc_getName(procId), INVALID_PROC) == 0) {
339         fprintf(stderr, "Unsupported core\n");
340         return (EPERM);
341     }
343     pthread_mutex_lock(&dev->firmwareLock);
345     for (i = 0; i < syslink_num_cores; i++) {
346         if (syslink_firmware[i].proc_id == procId) {
347             break;
348         }
349     }
350     if (i == syslink_num_cores) {
351         if ((syslink_num_cores < MultiProc_MAXPROCESSORS)) {
352             addFirmware(procId);
353         }
354         else {
355             pthread_mutex_unlock(&dev->firmwareLock);
356             return (EBADSLT);
357         }
358     }
360     if (ocb->ocb.offset == 0) {
361         /* latch onto new state, so that we print out complete strings */
362         syslink_firmware[i].readProcState = syslink_firmware[i].procState;
363     }
365     nleft = strlen(procStateNames[syslink_firmware[i].readProcState])
366         - ocb->ocb.offset; /* the state is expressed in one byte */
367     nbytes = min(msg->i.nbytes, nleft);
369     /* Make sure the user has supplied a big enough buffer */
370     if (nbytes > 0) {
371         /* set up the return data IOV */
372         SETIOV(ctp->iov,
373             (char *)procStateNames[syslink_firmware[i].readProcState]
374             + ocb->ocb.offset, nbytes);
376         pthread_mutex_unlock(&dev->firmwareLock);
378         /* set up the number of bytes (returned by client's read()) */
379         _IO_SET_READ_NBYTES(ctp, nbytes);
381         ocb->ocb.offset += nbytes;
383         nparts = 1;
384     }
385     else {
386         pthread_mutex_unlock(&dev->firmwareLock);
388         _IO_SET_READ_NBYTES (ctp, 0);
390         /* reset offset */
391         ocb->ocb.offset = 0;
393         nparts = 0;
394     }
396     /* mark the access time as invalid (we just accessed it) */
398     if (msg->i.nbytes > 0) {
399         ocb->ocb.attr->attr.flags |= IOFUNC_ATTR_ATIME;
400     }
402     return (_RESMGR_NPARTS(nparts));
405 static int slave_state_write(resmgr_context_t *ctp, io_write_t *msg,
406     syslink_ocb_t *ocb)
408     int             status;
409     char *          buf;
410     uint16_t        procId = ocb->ocb.attr->procid;
411     int             i;
412     char *          ptr;
413     syslink_dev_t * dev = ocb->ocb.attr->dev;
414     Int32           sr0ProcId;
416     if ((status = iofunc_write_verify(ctp, msg, &ocb->ocb, NULL)) != EOK) {
417         return (status);
418     }
420     if ((msg->i.xtype & _IO_XTYPE_MASK) != _IO_XTYPE_NONE) {
421         return (ENOSYS);
422     }
424     if (strcmp(MultiProc_getName(procId), INVALID_PROC) == 0) {
425         fprintf(stderr, "Unsupported core\n");
426         return (EPERM);
427     }
429     /* set up the number of bytes (returned by client's write()) */
430     _IO_SET_WRITE_NBYTES (ctp, msg->i.nbytes);
432     buf = (char *) malloc(msg->i.nbytes + 1);
433     if (buf == NULL) {
434         return (ENOMEM);
435     }
437     /*
438      *  Read the data from the sender's message buffer.
439      */
440     resmgr_msgread(ctp, buf, msg->i.nbytes, sizeof(msg->i));
441     buf[msg->i.nbytes] = '\0'; /* just in case the text is not NULL terminated */
442     if((ptr = strchr(buf, '\n')) != NULL) { /* Remove line feed if any */
443         *ptr = '\0';
444     }
446     pthread_mutex_lock(&dev->firmwareLock);
447     for (i = 0; i < syslink_num_cores; i++) {
448         if (syslink_firmware[i].proc_id == procId) {
449             break;
450         }
451     }
452     if (i == syslink_num_cores) {
453         if ((syslink_num_cores < MultiProc_MAXPROCESSORS)) {
454             addFirmware(procId);
455         }
456         else {
457             pthread_mutex_unlock(&dev->firmwareLock);
458             return (EBADSLT);
459         }
460     }
462     if (strcmp("1", buf) == 0) {
463         if ((syslink_firmware[i].procState == RESET_STATE) &&
464            (syslink_firmware[i].firmware != NULL)) {
465             runSlave(ocb->ocb.attr->dev, procId, &syslink_firmware[i]);
466 #if defined(SYSLINK_PLATFORM_VAYU)
467             if (gatempEnabled) {
468                 if (sr0OwnerProcId == -1) {
469                     /* Set up GateMP */
470                     status = GateMP_setup(&sr0ProcId);
471                     if ((status < 0) && (status != GateMP_E_NOTFOUND)) {
472                         resetSlave(ocb->ocb.attr->dev, procId);
473                         pthread_mutex_unlock(&dev->firmwareLock);
474                         free(buf);
475                         return (EIO);
476                     }
477                     else if (status == 0) {
478                         /* We have discovered an owner for SR0 */
479                         sr0OwnerProcId = sr0ProcId;
480                     }
481                 }
482                 else {
483                     /*
484                      * We have already identified SR0 owner and setup GateMP.
485                      * Do nothing.
486                      */
487                 }
488             }
489 #endif
490             printf("Core is now running with image '%s'\n",
491                 syslink_firmware[i].firmware);
492             syslink_firmware[i].procState = RUNNING_STATE;
493             syslink_firmware[i].reload = true;
494             status = init_syslink_trace_device(dev);
495             if (status < 0) {
496                 pthread_mutex_unlock(&dev->firmwareLock);
497                 free(buf);
498                 return (EIO);
499             }
500             printf("Core %s has been started.\n", MultiProc_getName(procId));
501         }
502     }
503     else if (strcmp("0", buf) == 0) {
504         if (syslink_firmware[i].procState == RUNNING_STATE) {
505 #if defined(SYSLINK_PLATFORM_VAYU)
506             if ((gatempEnabled) && (procId == sr0OwnerProcId)) {
507                 sr0OwnerProcId = -1;
508                 status = GateMP_destroy(FALSE);
509                 if (status < 0) {
510                     pthread_mutex_unlock(&dev->firmwareLock);
511                     free(buf);
512                     fprintf(stderr, "Core %s cannot be reset. GateMP may still"
513                         " be in use by host\n", MultiProc_getName(procId));
514                     return (EIO);
515                 }
516             }
517 #endif
518             resetSlave(ocb->ocb.attr->dev, procId);
519             syslink_firmware[i].procState = RESET_STATE;
520             syslink_firmware[i].reload = false;
521             status = deinit_syslink_trace_device(dev);
522             if (status < 0) {
523                 pthread_mutex_unlock(&dev->firmwareLock);
524                 free(buf);
525                 Osal_printf("IPC: deinit_syslink_trace_device failed %d",
526                     status);
527                 return (EIO);
528             }
529             printf("Core %s has been reset.\n", MultiProc_getName(procId));
530         }
531     }
532     else {
533         /* ignore the input as it is not recognized */
534         fprintf(stderr, "Unrecognized input\n");
535     }
537     pthread_mutex_unlock(&dev->firmwareLock);
539     free(buf);
541     if (msg->i.nbytes > 0) {
542         ocb->ocb.attr->attr.flags |= IOFUNC_ATTR_MTIME | IOFUNC_ATTR_CTIME;
543     }
545     return (_RESMGR_NPARTS(0));
548 static int slave_file_read(resmgr_context_t *ctp, io_read_t *msg,
549     syslink_ocb_t *ocb)
551     int             nbytes;
552     int             nparts;
553     int             status;
554     int             nleft;
555     int             i;
556     uint16_t        procId = ocb->ocb.attr->procid;
557     syslink_dev_t * dev = ocb->ocb.attr->dev;
559     if ((status = iofunc_read_verify (ctp, msg, &ocb->ocb, NULL)) != EOK) {
560         return (status);
561     }
563     if ((msg->i.xtype & _IO_XTYPE_MASK) != _IO_XTYPE_NONE) {
564         return (ENOSYS);
565     }
567     if (strcmp(MultiProc_getName(procId), INVALID_PROC) == 0) {
568         fprintf(stderr, "Unsupported core\n");
569         return (EPERM);
570     }
572     pthread_mutex_lock(&dev->firmwareLock);
573     for (i = 0; i < syslink_num_cores; i++) {
574         if (syslink_firmware[i].proc_id == procId) {
575             break;
576         }
577     }
579     if (i == syslink_num_cores) {
580         if ((syslink_num_cores < MultiProc_MAXPROCESSORS)) {
581             addFirmware(procId);
582         }
583         else {
584             pthread_mutex_unlock(&dev->firmwareLock);
585             return (EBADSLT);
586         }
587     }
589     if (syslink_firmware[i].firmware == NULL) {
590         nbytes = 0;
591     }
592     else {
593         nleft = strlen(syslink_firmware[i].firmware)
594             - ocb->ocb.offset + 1; /* Add one byte for carriage return */
595         nbytes = min(msg->i.nbytes, nleft);
596     }
598     /* Make sure the user has supplied a big enough buffer */
599     if (nbytes > 0) {
600         if (nbytes == nleft) {
601             /* set up the return data IOV */
602             SETIOV(&ctp->iov[0], (char *)syslink_firmware[i].firmware
603                 + ocb->ocb.offset, nbytes - 1);
605             /* add a carriage return */
606             SETIOV(&ctp->iov[1], "\n", 1);
608             nparts = 2;
609         }
610         else {
611             /* set up the return data IOV */
612             SETIOV(ctp->iov, (char *)syslink_firmware[i].firmware
613                 + ocb->ocb.offset, nbytes);
615             nparts = 1;
616         }
618         /* set up the number of bytes (returned by client's read()) */
619         _IO_SET_READ_NBYTES(ctp, nbytes);
621         ocb->ocb.offset += nbytes;
622     }
623     else {
624         _IO_SET_READ_NBYTES (ctp, 0);
626         /* reset offset */
627         ocb->ocb.offset = 0;
629         nparts = 0;
630     }
632     pthread_mutex_unlock(&dev->firmwareLock);
634     /* mark the access time as invalid (we just accessed it) */
636     if (msg->i.nbytes > 0) {
637         ocb->ocb.attr->attr.flags |= IOFUNC_ATTR_ATIME;
638     }
640     return (_RESMGR_NPARTS(nparts));
643 static int slave_file_write(resmgr_context_t *ctp, io_write_t *msg,
644     syslink_ocb_t *ocb)
646     int             status;
647     char *          buf;
648     uint16_t        procId = ocb->ocb.attr->procid;
649     int             i;
650     char *          absPath;
651     char *          ptr;
652     syslink_dev_t * dev = ocb->ocb.attr->dev;
654     if ((status = iofunc_write_verify(ctp, msg, &ocb->ocb, NULL)) != EOK) {
655         return (status);
656     }
658     if ((msg->i.xtype & _IO_XTYPE_MASK) != _IO_XTYPE_NONE) {
659         return (ENOSYS);
660     }
662     if (strcmp(MultiProc_getName(procId), INVALID_PROC) == 0) {
663         fprintf(stderr, "Unsupported core\n");
664         return (EPERM);
665     }
667     /* set up the number of bytes (returned by client's write()) */
668     _IO_SET_WRITE_NBYTES (ctp, msg->i.nbytes);
670     buf = (char *) malloc(msg->i.nbytes + 1);
671     if (buf == NULL) {
672         return (ENOMEM);
673     }
675     /*
676      *  Read the data from the sender's message buffer.
677      */
678     resmgr_msgread(ctp, buf, msg->i.nbytes, sizeof(msg->i));
679     buf[msg->i.nbytes] = '\0'; /* just in case the text is not NULL terminated */
680     if((ptr = strchr(buf, '\n')) != NULL) { /* Remove line feed if any */
681         *ptr = '\0';
682     }
684     /* Get the abs path for all firmware files */
685     absPath = calloc(1, PATH_MAX + 1);
686     if (absPath == NULL) {
687         free(buf);
688         return (ENOMEM);
689     }
690     if (NULL == realpath(buf, absPath)) {
691         fprintf(stderr, "invalid path to executable: %d\n", errno);
692         fprintf(stderr, "make sure you are specifying the full path to the "
693             "file.\n");
694         free(absPath);
695         free(buf);
696         return (ENOENT);
697     }
698     free(buf);
700     pthread_mutex_lock(&dev->firmwareLock);
702     /*
703      * Check if an entry in syslink_firmware already exists for this core.
704      * If not, create one. Otherwise just update the firmware path.
705      */
706     for (i = 0; i < syslink_num_cores; i++) {
707         if (syslink_firmware[i].proc_id == procId) {
708             break;
709         }
710     }
711     if (i == syslink_num_cores) {
712         if (syslink_num_cores < MultiProc_MAXPROCESSORS) {
713             addFirmware(procId);
714             syslink_firmware[syslink_num_cores - 1].freeString = true;
715             syslink_firmware[syslink_num_cores - 1].firmware = absPath;
716         }
717         else {
718             pthread_mutex_unlock(&dev->firmwareLock);
719             free(absPath);
720             return (EBADSLT);
721         }
722     }
723     else {
724         /* Free previously allocated string */
725         if ((syslink_firmware[i].freeString) &&
726            (syslink_firmware[i].firmware)) {
727             free(syslink_firmware[i].firmware);
728         }
729         syslink_firmware[i].firmware = absPath;
730     }
732     pthread_mutex_unlock(&dev->firmwareLock);
734     if (msg->i.nbytes > 0) {
735         ocb->ocb.attr->attr.flags |= IOFUNC_ATTR_MTIME | IOFUNC_ATTR_CTIME;
736     }
738     return (_RESMGR_NPARTS(0));
741 int syslink_read(resmgr_context_t *ctp, io_read_t *msg, syslink_ocb_t *ocb)
743     int         nbytes;
744     int         nparts;
745     int         status;
746     int         nleft;
747     uint32_t    len;
748     uint16_t    procid = ocb->ocb.attr->procid;
750     if ((status = iofunc_read_verify (ctp, msg, &ocb->ocb, NULL)) != EOK)
751         return (status);
753     if ((msg->i.xtype & _IO_XTYPE_MASK) != _IO_XTYPE_NONE)
754         return (ENOSYS);
756     /* check to see where the trace buffer is */
757     if (proc_traces[procid].va == NULL) {
758         return (ENOSYS);
759     }
760     if (ocb->ocb.offset == 0) {
761         ocb->widx = *(proc_traces[procid].widx);
762         ocb->ridx = *(proc_traces[procid].ridx);
763         *(proc_traces[procid].ridx) = ocb->widx;
764     }
766     /* Check for wrap-around */
767     if (ocb->widx < ocb->ridx)
768         len = proc_traces[procid].len - ocb->ridx + ocb->widx;
769     else
770         len = ocb->widx - ocb->ridx;
772     /* Determine the amount left to print */
773     if (ocb->widx >= ocb->ridx)
774         nleft = len - ocb->ocb.offset;
775     else if (ocb->ocb.offset < proc_traces[procid].len - ocb->ridx)
776         nleft = proc_traces[procid].len - ocb->ridx - ocb->ocb.offset;
777     else
778         nleft = proc_traces[procid].len - ocb->ridx + ocb->widx - ocb->ocb.offset;
780     nbytes = min (msg->i.nbytes, nleft);
782     /* Make sure the user has supplied a big enough buffer */
783     if (nbytes > 0) {
784         /* set up the return data IOV */
785         if (ocb->widx < ocb->ridx && ocb->ocb.offset >= proc_traces[procid].len - ocb->ridx)
786             SETIOV (ctp->iov, (char *)proc_traces[procid].va + ocb->ocb.offset - (proc_traces[procid].len - ocb->ridx), nbytes);
787         else
788             SETIOV (ctp->iov, (char *)proc_traces[procid].va + ocb->ridx + ocb->ocb.offset, nbytes);
790         /* set up the number of bytes (returned by client's read()) */
791         _IO_SET_READ_NBYTES (ctp, nbytes);
793         ocb->ocb.offset += nbytes;
795         nparts = 1;
796     }
797     else {
798         _IO_SET_READ_NBYTES (ctp, 0);
800         /* reset offset */
801         ocb->ocb.offset = 0;
803         nparts = 0;
804     }
806     /* mark the access time as invalid (we just accessed it) */
808     if (msg->i.nbytes > 0)
809         ocb->ocb.attr->attr.flags |= IOFUNC_ATTR_ATIME;
811     return (_RESMGR_NPARTS (nparts));
814 extern OsalSemaphore_Handle mqcopy_test_sem;
816 int syslink_unblock(resmgr_context_t *ctp, io_pulse_t *msg, syslink_ocb_t *ocb)
818     int status = _RESMGR_NOREPLY;
819     struct _msg_info info;
821     /*
822      * Try to run the default unblock for this message.
823      */
824     if ((status = iofunc_unblock_default(ctp,msg,&(ocb->ocb))) != _RESMGR_DEFAULT) {
825         return status;
826     }
828     /*
829      * Check if rcvid is still valid and still has an unblock
830      * request pending.
831      */
832     if (MsgInfo(ctp->rcvid, &info) == -1 ||
833         !(info.flags & _NTO_MI_UNBLOCK_REQ)) {
834         return _RESMGR_NOREPLY;
835     }
837     if (mqcopy_test_sem)
838         OsalSemaphore_post(mqcopy_test_sem);
840     return _RESMGR_NOREPLY;
843 IOFUNC_OCB_T *
844 syslink_ocb_calloc (resmgr_context_t * ctp, IOFUNC_ATTR_T * device)
846     syslink_ocb_t *ocb = NULL;
848     /* Allocate the OCB */
849     ocb = (syslink_ocb_t *) calloc (1, sizeof (syslink_ocb_t));
850     if (ocb == NULL){
851         errno = ENOMEM;
852         return (NULL);
853     }
855     ocb->pid = ctp->info.pid;
857     return (IOFUNC_OCB_T *)(ocb);
860 void
861 syslink_ocb_free (IOFUNC_OCB_T * i_ocb)
863     syslink_ocb_t * ocb = (syslink_ocb_t *)i_ocb;
865     if (ocb) {
866 #ifndef SYSLINK_PLATFORM_VAYU
867         GateHWSpinlock_LeaveLockForPID(ocb->pid);
868 #endif
869         free (ocb);
870     }
873 int init_slave_devices(syslink_dev_t *dev)
875     resmgr_attr_t    resmgr_attr;
876     int              i;
877     syslink_attr_t * slave_attr;
878     int              status = 0;
880     memset(&resmgr_attr, 0, sizeof resmgr_attr);
881     resmgr_attr.nparts_max = 2;
882     resmgr_attr.msg_max_size = _POSIX_PATH_MAX;
884     /* Populate the /dev/ipc-state namespace */
885     for (i = 1; i < MultiProc_getNumProcessors(); i++) {
886         iofunc_func_init(_RESMGR_CONNECT_NFUNCS, &dev->syslink.cfuncs_state[i],
887                          _RESMGR_IO_NFUNCS, &dev->syslink.iofuncs_state[i]);
888         slave_attr = &dev->syslink.cattr_slave[i];
889         iofunc_attr_init(&slave_attr->attr,
890                          S_IFCHR | 0777, NULL, NULL);
891         slave_attr->attr.mount = &dev->syslink.mattr;
892         slave_attr->procid = i;
893         slave_attr->dev = (Ptr)dev;
894         iofunc_time_update(&slave_attr->attr);
895         snprintf(dev->syslink.device_name, _POSIX_PATH_MAX,
896                   "%s-state/%s", IPC_DEVICE_PATH, MultiProc_getName(i));
897         dev->syslink.iofuncs_state[i].read = slave_state_read;
898         dev->syslink.iofuncs_state[i].write = slave_state_write;
900         if (-1 == (dev->syslink.resmgr_id_state[i] =
901             resmgr_attach(dev->dpp, &resmgr_attr,
902                 dev->syslink.device_name, _FTYPE_ANY, 0,
903                 &dev->syslink.cfuncs_state[i],
904                 &dev->syslink.iofuncs_state[i],
905                 &slave_attr->attr))) {
906             GT_setFailureReason(curTrace, GT_4CLASS, "init_slave_devices",
907                 status, "resmgr_attach failed");
908             return (-1);
909         }
910     }
912     /* Populate the /dev/ipc-file namespace */
913     for (i = 1; i < MultiProc_getNumProcessors(); i++) {
914         iofunc_func_init(_RESMGR_CONNECT_NFUNCS, &dev->syslink.cfuncs_file[i],
915                          _RESMGR_IO_NFUNCS, &dev->syslink.iofuncs_file[i]);
916         slave_attr = &dev->syslink.cattr_slave[i];
917         iofunc_attr_init(&slave_attr->attr,
918                          S_IFCHR | 0777, NULL, NULL);
919         slave_attr->attr.mount = &dev->syslink.mattr;
920         slave_attr->procid = i;
921         slave_attr->dev = (Ptr)dev;
922         iofunc_time_update(&slave_attr->attr);
923         snprintf(dev->syslink.device_name, _POSIX_PATH_MAX,
924                   "%s-file/%s", IPC_DEVICE_PATH, MultiProc_getName(i));
925         dev->syslink.iofuncs_file[i].read = slave_file_read;
926         dev->syslink.iofuncs_file[i].write = slave_file_write;
928         if (-1 == (dev->syslink.resmgr_id_file[i] =
929             resmgr_attach(dev->dpp, &resmgr_attr,
930                 dev->syslink.device_name, _FTYPE_ANY, 0,
931                 &dev->syslink.cfuncs_file[i],
932                 &dev->syslink.iofuncs_file[i],
933                 &slave_attr->attr))) {
934             GT_setFailureReason(curTrace, GT_4CLASS, "init_slave_devices",
935                 status, "resmgr_attach failed");
936             return (-1);
937         }
938     }
940     return (status);
943 int deinit_slave_devices(syslink_dev_t *dev)
945     int status = EOK;
946     int i = 0;
948     for (i = 1; i < MultiProc_getNumProcessors(); i++) {
949         status = resmgr_detach(dev->dpp, dev->syslink.resmgr_id_state[i], 0);
950         if (status < 0) {
951             Osal_printf("IPC: resmgr_detach of state device %d failed: %d",
952                 i, errno);
953         }
954         status = resmgr_detach(dev->dpp, dev->syslink.resmgr_id_file[i], 0);
955         if (status < 0) {
956             Osal_printf("IPC: resmgr_detach of file device %d failed: %d",
957                 i, errno);
958         }
959     }
961     return (status);
964 int init_syslink_trace_device(syslink_dev_t *dev)
966     resmgr_attr_t    resmgr_attr;
967     int              i;
968     syslink_attr_t * trace_attr;
969     char             trace_name[_POSIX_PATH_MAX];
970     int              status = 0;
971     unsigned int     da = 0, pa = 0;
972     unsigned int     len;
974     memset(&resmgr_attr, 0, sizeof resmgr_attr);
975     resmgr_attr.nparts_max = 10;
976     resmgr_attr.msg_max_size = 2048;
978     for (i = 0; i < syslink_num_cores; i++) {
979         /*
980          * Initialize trace device only for cores that are running and their
981          * device is not yet setup.
982          */
983         if ((syslink_firmware[i].procState == RUNNING_STATE) &&
984             (proc_traces[i].va == NULL)) {
985             iofunc_func_init(_RESMGR_CONNECT_NFUNCS,
986                 &dev->syslink.cfuncs_trace[i],
987                 _RESMGR_IO_NFUNCS, &dev->syslink.iofuncs_trace[i]);
988             trace_attr = &dev->syslink.cattr_trace[i];
989             iofunc_attr_init(&trace_attr->attr,
990                          S_IFCHR | 0777, NULL, NULL);
991             trace_attr->attr.mount = &dev->syslink.mattr;
992             trace_attr->procid = i;
993             iofunc_time_update(&trace_attr->attr);
994             snprintf (dev->syslink.device_name, _POSIX_PATH_MAX,
995                   "/dev/ipc-trace%d", syslink_firmware[i].proc_id);
996             dev->syslink.iofuncs_trace[i].read = syslink_read;
997             snprintf (trace_name, _POSIX_PATH_MAX, "%d", 0);
998             pa = 0;
999             status = RscTable_getInfo(syslink_firmware[i].proc_id, TYPE_TRACE,
1000                 0, &da, &pa, &len);
1001             if (status == 0) {
1002                 /* last 8 bytes are for writeIdx/readIdx */
1003                 proc_traces[i].len = len - (sizeof(uint32_t) * 2);
1004                 if (da && !pa) {
1005                     /* need to translate da->pa */
1006                     status = ProcMgr_translateAddr(
1007                         procH[syslink_firmware[i].proc_id],
1008                         (Ptr *) &pa,
1009                         ProcMgr_AddrType_MasterPhys,
1010                         (Ptr) da,
1011                         ProcMgr_AddrType_SlaveVirt);
1012                 }
1013                 else {
1014                     GT_setFailureReason(curTrace, GT_4CLASS,
1015                         "init_syslink_trace_device",
1016                         status, "not performing ProcMgr_translate");
1017                 }
1018                 /* map length aligned to page size */
1019                 proc_traces[i].va =
1020                     mmap_device_io (((len + 0x1000 - 1) / 0x1000) * 0x1000, pa);
1021                 proc_traces[i].widx = (uint32_t *)(proc_traces[i].va + \
1022                                                proc_traces[i].len);
1023                 proc_traces[i].ridx = (uint32_t *)((uint32_t)proc_traces[i].widx
1024                     + sizeof(uint32_t));
1025                 if (proc_traces[i].va == MAP_DEVICE_FAILED) {
1026                     GT_setFailureReason(curTrace, GT_4CLASS,
1027                         "init_syslink_trace_device",
1028                         status, "mmap_device_io failed");
1029                     GT_1trace(curTrace, GT_4CLASS, "errno %d", errno);
1030                     proc_traces[i].va = NULL;
1031                 }
1032                 proc_traces[i].firstRead = TRUE;
1033             }
1034             else {
1035                 GT_setFailureReason(curTrace, GT_4CLASS,
1036                     "init_syslink_trace_device",
1037                     status, "RscTable_getInfo failed");
1038                 proc_traces[i].va = NULL;
1039             }
1040             if (-1 == (dev->syslink.resmgr_id_trace[i] =
1041                        resmgr_attach(dev->dpp, &resmgr_attr,
1042                                      dev->syslink.device_name, _FTYPE_ANY, 0,
1043                                      &dev->syslink.cfuncs_trace[i],
1044                                      &dev->syslink.iofuncs_trace[i],
1045                                      &trace_attr->attr))) {
1046                 GT_setFailureReason(curTrace, GT_4CLASS,
1047                     "init_syslink_trace_device",
1048                     status, "resmgr_attach failed");
1049                 return(-1);
1050             }
1051         }
1052     }
1054     return (status);
1057 int deinit_syslink_trace_device(syslink_dev_t *dev)
1059     int status = EOK;
1060     int i = 0;
1062     for (i = 0; i < syslink_num_cores; i++) {
1063         /* Only disable trace device on cores in RESET state */
1064         if ((syslink_firmware[i].procState == RESET_STATE) &&
1065             (proc_traces[i].va != NULL)) {
1066             status = resmgr_detach(dev->dpp, dev->syslink.resmgr_id_trace[i],
1067                 0);
1068             if (status < 0) {
1069                 Osal_printf("IPC: resmgr_detach of trace device %d failed: %d",
1070                     i, errno);
1071                 status = errno;
1072             }
1073             if (proc_traces[i].va && proc_traces[i].va != MAP_DEVICE_FAILED) {
1074                 munmap((void *)proc_traces[i].va,
1075                    ((proc_traces[i].len + 8 + 0x1000 - 1) / 0x1000) * 0x1000);
1076             }
1077             proc_traces[i].va = NULL;
1078         }
1079     }
1081     return (status);
1084 /* Initialize the syslink device */
1085 int init_syslink_device(syslink_dev_t *dev)
1087     iofunc_attr_t *  attr;
1088     resmgr_attr_t    resmgr_attr;
1089     int              status = 0;
1091     pthread_mutex_init(&dev->lock, NULL);
1092     pthread_mutex_init(&dev->firmwareLock, NULL);
1094     memset(&resmgr_attr, 0, sizeof resmgr_attr);
1095     resmgr_attr.nparts_max = 10;
1096     resmgr_attr.msg_max_size = 2048;
1098     memset(&dev->syslink.mattr, 0, sizeof(iofunc_mount_t));
1099     dev->syslink.mattr.flags = ST_NOSUID | ST_NOEXEC;
1100     dev->syslink.mattr.conf = IOFUNC_PC_CHOWN_RESTRICTED |
1101                               IOFUNC_PC_NO_TRUNC |
1102                               IOFUNC_PC_SYNC_IO;
1103     dev->syslink.mattr.funcs = &dev->syslink.mfuncs;
1105     memset(&dev->syslink.mfuncs, 0, sizeof(iofunc_funcs_t));
1106     dev->syslink.mfuncs.nfuncs = _IOFUNC_NFUNCS;
1108     iofunc_func_init(_RESMGR_CONNECT_NFUNCS, &dev->syslink.cfuncs,
1109                     _RESMGR_IO_NFUNCS, &dev->syslink.iofuncs);
1111     iofunc_attr_init(attr = &dev->syslink.cattr, S_IFCHR | 0777, NULL, NULL);
1113     dev->syslink.mfuncs.ocb_calloc = syslink_ocb_calloc;
1114     dev->syslink.mfuncs.ocb_free = syslink_ocb_free;
1115     dev->syslink.iofuncs.devctl = syslink_devctl;
1116     dev->syslink.iofuncs.unblock = syslink_unblock;
1118     attr->mount = &dev->syslink.mattr;
1119     iofunc_time_update(attr);
1121     if (-1 == (dev->syslink.resmgr_id =
1122         resmgr_attach(dev->dpp, &resmgr_attr,
1123                       IPC_DEVICE_PATH, _FTYPE_ANY, 0,
1124                       &dev->syslink.cfuncs,
1125                       &dev->syslink.iofuncs, attr))) {
1126         return(-1);
1127     }
1129     status = init_slave_devices(dev);
1130     if (status < 0) {
1131         return status;
1132     }
1134     status = init_syslink_trace_device(dev);
1135     if (status < 0) {
1136         return status;
1137     }
1139     return(0);
1142 /* De-initialize the syslink device */
1143 int deinit_syslink_device(syslink_dev_t *dev)
1145     int status = EOK;
1147     status = resmgr_detach(dev->dpp, dev->syslink.resmgr_id, 0);
1148     if (status < 0) {
1149         Osal_printf("IPC: resmgr_detach of %s failed: %d",
1150             IPC_DEVICE_PATH, errno);
1151         status = errno;
1152     }
1154     status = deinit_syslink_trace_device(dev);
1155     if (status < 0) {
1156         Osal_printf("IPC: deinit_syslink_trace_device failed %d", status);
1157     }
1159     status = deinit_slave_devices(dev);
1160     if (status < 0) {
1161         Osal_printf("IPC: deinit_slave_devices failed %d", status);
1162     }
1164     return(status);
1168 /* Initialize the devices */
1169 int init_devices(syslink_dev_t *dev)
1171     if (init_syslink_device(dev) < 0) {
1172         Osal_printf("IPC: device init failed");
1173         return(-1);
1174     }
1176     return(0);
1180 /* De-initialize the devices */
1181 int deinit_devices(syslink_dev_t *dev)
1183     int status = EOK;
1185     if ((status = deinit_syslink_device(dev)) < 0) {
1186         fprintf( stderr, "IPC: device de-init failed %d\n", status);
1187         status = errno;
1188     }
1190     return(status);
1193 static void ipc_recover(Ptr args)
1195     syslink_dev_t * dev = (syslink_dev_t *)args;
1197     if (!disableRecovery) {
1198         /* Protect the syslink_firmware array as we recover */
1199         pthread_mutex_lock(&dev->firmwareLock);
1200         deinit_ipc(dev, syslink_firmware, TRUE);
1201         deinit_syslink_trace_device(dev);
1202         init_ipc(dev, syslink_firmware, TRUE);
1203         init_syslink_trace_device(dev);
1204         pthread_mutex_unlock(&dev->firmwareLock);
1205     }
1206     else {
1207         GT_0trace(curTrace, GT_4CLASS,
1208                   "ipc_recover: Recovery disabled.\n");
1209     }
1212 Int syslink_error_cb (UInt16 procId, ProcMgr_Handle handle,
1213                       ProcMgr_State fromState, ProcMgr_State toState,
1214                       ProcMgr_EventStatus status, Ptr args)
1216     Int ret = 0;
1217     String errString = NULL;
1218     syslink_dev_t * dev = (syslink_dev_t *)args;
1220     if (status == ProcMgr_EventStatus_Event) {
1221         switch (toState) {
1222             case ProcMgr_State_Mmu_Fault:
1223                 errString = "MMU Fault";
1224                 break;
1225             case ProcMgr_State_Error:
1226                 errString = "Exception";
1227                 break;
1228             case ProcMgr_State_Watchdog:
1229                 errString = "Watchdog";
1230                 break;
1231             default:
1232                 errString = "Unexpected State";
1233                 ret = -1;
1234                 break;
1235         }
1236         GT_2trace (curTrace, GT_4CLASS,
1237                    "syslink_error_cb: Received Error Callback for %s : %s\n",
1238                    MultiProc_getName(procId), errString);
1239         /* Don't allow re-schedule of recovery until complete */
1240         pthread_mutex_lock(&dev->lock);
1241         if (ret != -1 && dev->recover == FALSE) {
1242             /* Schedule recovery. */
1243             dev->recover = TRUE;
1244             /* Activate a thread to handle the recovery. */
1245             GT_0trace (curTrace, GT_4CLASS,
1246                        "syslink_error_cb: Scheduling recovery...");
1247             OsalThread_activate(dev->ipc_recovery_work);
1248         }
1249         else {
1250             GT_0trace (curTrace, GT_4CLASS,
1251                        "syslink_error_cb: Recovery already scheduled.");
1252         }
1253         pthread_mutex_unlock(&dev->lock);
1254     }
1255     else if (status == ProcMgr_EventStatus_Canceled) {
1256         GT_1trace (curTrace, GT_3CLASS,
1257                    "SysLink Error Callback Cancelled for %s",
1258                    MultiProc_getName(procId));
1259     }
1260     else {
1261         GT_1trace (curTrace, GT_4CLASS,
1262                    "SysLink Error Callback Unexpected Event for %s",
1263                    MultiProc_getName(procId));
1264     }
1266     return ret;
1269 /*
1270  * Initialize the syslink ipc
1271  *
1272  * This function sets up the "kernel"-side IPC modules, and does any special
1273  * initialization required for QNX and the platform being used.  This function
1274  * also registers for error notifications and initializes the recovery thread.
1275  */
1276 int init_ipc(syslink_dev_t * dev, syslink_firmware_info * firmware, bool recover)
1278     int status = 0;
1279     Ipc_Config iCfg;
1280     OsalThread_Params threadParams;
1281     UInt16 procId;
1282     int i;
1284     if (status >= 0) {
1285         if (!recover) {
1286             /* Set up the MemoryOS module */
1287             status = MemoryOS_setup();
1288             if (status < 0)
1289                 goto memoryos_fail;
1290         }
1292         /* Setup IPC and platform-specific items */
1293         status = Ipc_setup (&iCfg);
1294         if (status < 0)
1295             goto ipcsetup_fail;
1297         /* NOTE: this is for handling the procmgr event notifications to userspace list */
1298         if (!recover) {
1299             /* Setup Fault recovery items. */
1300             /* Create the thread object used for the interrupt handler. */
1301             threadParams.priority     = OsalThread_Priority_Medium;
1302             threadParams.priorityType = OsalThread_PriorityType_Generic;
1303             threadParams.once         = FALSE;
1304             dev->ipc_recovery_work = OsalThread_create ((OsalThread_CallbackFxn)
1305                                                         ipc_recover,
1306                                                         dev,
1307                                                         &threadParams);
1308             if (dev->ipc_recovery_work == NULL)
1309                 goto osalthreadcreate_fail;
1310         }
1311         else {
1312             pthread_mutex_lock(&dev->lock);
1313             dev->recover = FALSE;
1314             pthread_mutex_unlock(&dev->lock);
1315         }
1317         memset(procH_fileId, 0, sizeof(procH_fileId));
1319         for (i = 0; i < syslink_num_cores; i++) {
1320             procId = firmware[i].proc_id = MultiProc_getId(firmware[i].proc);
1321             if (procId >= MultiProc_MAXPROCESSORS) {
1322                 status = -1;
1323                 fprintf(stderr, "Invalid processor name specified\n");
1324                 break;
1325             }
1327             if (procH[procId]) {
1328                 GT_setFailureReason (curTrace,
1329                                      GT_4CLASS,
1330                                      "init_ipc",
1331                                      status,
1332                                      "invalid proc!");
1333                 break;
1334             }
1336             if (recover) {
1337                 /*
1338                  * if we are in recovery, we load the cores we previously
1339                  * attached to
1340                  */
1341                 firmware[i].attachOnly = false;
1342             }
1344             if ((!recover) || (firmware[i].reload)) {
1345                 status = runSlave(dev, procId, &firmware[i]);
1346                 if (status == 0) {
1347                     firmware[i].procState = RUNNING_STATE;
1348                     continue;
1349                 }
1350                 else {
1351                     break;
1352                 }
1353             }
1354             else {
1355                 /*
1356                  * During recovery, do not run cores unless they were previously
1357                  * running
1358                  */
1359                 continue;
1360             }
1361         }
1363         if (status < 0)
1364             goto tiipcsetup_fail;
1366         /* Set up rpmsg_mq */
1367         status = ti_ipc_setup();
1368         if (status < 0)
1369             goto tiipcsetup_fail;
1371         /* Set up rpmsg_rpc */
1372         status = rpmsg_rpc_setup();
1373         if (status < 0)
1374             goto rpcsetup_fail;
1376 #if defined(SYSLINK_PLATFORM_VAYU)
1377         if (gatempEnabled) {
1378             Int32 sr0ProcId;
1380             /* Set up NameServer for resource manager process */
1381             status = NameServer_setup();
1382             if (status < 0) {
1383                 goto nameserversetup_fail;
1384             }
1386             /* Set up GateMP */
1387             status = GateMP_setup(&sr0ProcId);
1388             if ((status < 0) && (status != GateMP_E_NOTFOUND)) {
1389                 goto gatempsetup_fail;
1390             }
1391             else if (status == 0) {
1392                 sr0OwnerProcId = sr0ProcId;
1393             }
1394             else {
1395                 /*
1396                  * If we did not find the default gate, perhaps SR0 is
1397                  * not yet loaded. This is ok.
1398                  */
1399                 status = 0;
1400             }
1401         }
1402 #endif
1404         goto exit;
1405     }
1407 #if defined(SYSLINK_PLATFORM_VAYU)
1408 gatempsetup_fail:
1409     NameServer_destroy();
1410 nameserversetup_fail:
1411     rpmsg_rpc_destroy();
1412 #endif
1413 rpcsetup_fail:
1414     ti_ipc_destroy(recover);
1415 tiipcsetup_fail:
1416     for (i-=1; i >= 0; i--) {
1417         procId = firmware[i].proc_id;
1418         if (procId >= MultiProc_MAXPROCESSORS) {
1419             continue;
1420         }
1421         ProcMgr_unregisterNotify(procH[procId], syslink_error_cb,
1422                                 (Ptr)dev, errStates);
1423         if (!firmware[i].attachOnly) {
1424             ProcMgr_stop(procH[procId]);
1425             if (procH_fileId[procId]) {
1426                 ProcMgr_unload(procH[procId], procH_fileId[procId]);
1427                 procH_fileId[procId] = 0;
1428             }
1429         }
1430         ProcMgr_detach(procH[procId]);
1431         ProcMgr_close(&procH[procId]);
1432         procH[procId] = NULL;
1433         RscTable_free(&rscHandle[procId]);
1434         rscHandle[procId] = NULL;
1435     }
1436     OsalThread_delete(&dev->ipc_recovery_work);
1437 osalthreadcreate_fail:
1438     Ipc_destroy();
1439 ipcsetup_fail:
1440     MemoryOS_destroy();
1441 memoryos_fail:
1442 exit:
1443     return status;
1446 int deinit_ipc(syslink_dev_t * dev, syslink_firmware_info * firmware,
1447     bool recover)
1449     int status = EOK;
1450     uint32_t i = 0, id = 0;
1452     if (logFilename) {
1453         /* wait a little bit for traces to finish dumping */
1454         sleep(1);
1455     }
1457     // Stop the remote cores right away
1458     for (i = 0; i < MultiProc_MAXPROCESSORS; i++) {
1459         if (procH[i]) {
1460             resetSlave(dev, i);
1461         }
1462     }
1464 #if defined(SYSLINK_PLATFORM_VAYU)
1465     if (gatempEnabled) {
1466         GateMP_destroy(TRUE);
1468         NameServer_destroy();
1469     }
1470 #endif
1472     rpmsg_rpc_destroy();
1474     ti_ipc_destroy(recover);
1476     if (!recover && dev->ipc_recovery_work != NULL) {
1477         OsalThread_delete (&dev->ipc_recovery_work);
1478         dev->ipc_recovery_work = NULL;
1479     }
1481     if (recover) {
1482         static FILE *log = NULL;
1483         if (logFilename) {
1484             /* Dump the trace information */
1485             Osal_printf("IPC: printing remote core trace dump");
1486             log = fopen(logFilename, "a+");
1487             if (log) {
1488                 for (id = 0; id < syslink_num_cores; id++) {
1489                     if (firmware[id].procState == RUNNING_STATE) {
1490                         if (proc_traces[id].va) {
1491                             /* print traces */
1492                             fprintf(log, "*************************************\n");
1493                             fprintf(log, "***       CORE%d TRACE DUMP        ***\n",
1494                                 firmware[i].proc_id);
1495                             fprintf(log, "*************************************\n");
1496                             for (i = (*proc_traces[id].widx + 1);
1497                                 i < (proc_traces[id].len - 8);
1498                                 i++) {
1499                                 fprintf(log, "%c",
1500                                     *(char *)((uint32_t)proc_traces[id].va + i));
1501                             }
1502                             for (i = 0; i < *proc_traces[id].widx; i++) {
1503                                 fprintf(log, "%c",
1504                                     *(char *)((uint32_t)proc_traces[id].va + i));
1505                             }
1506                         }
1507                     }
1508                 }
1509                 fflush(log);
1510                 fclose(log);
1511             }
1512             else {
1513                 fprintf(stderr, "\nERROR: unable to open crash dump file %s\n",
1514                     logFilename);
1515                 exit(EXIT_FAILURE);
1516             }
1517         }
1518     }
1520     /* After printing trace, set all processor states to RESET */
1521     for (id = 0; id < syslink_num_cores; id++) {
1522         firmware[id].procState = RESET_STATE;
1523     }
1525     status = Ipc_destroy();
1526     if (status < 0) {
1527         printf("Ipc_destroy() failed 0x%x", status);
1528     }
1529     if (!recover) {
1530         status = MemoryOS_destroy();
1531         if (status < 0) {
1532             printf("MemoryOS_destroy() failed 0x%x", status);
1533         }
1534     }
1536     return status;
1540 /** print usage */
1541 static Void printUsage (Char * app)
1543     printf("\n\nUsage:\n");
1544 #if defined(SYSLINK_PLATFORM_OMAP5430)
1545     printf("\n%s: [-HTdca] <core_id1> <executable1> [<core_id2> <executable2> ...]\n",
1546         app);
1547     printf("  <core_id#> should be set to a core name (e.g. IPU, DSP)\n");
1548     printf("      followed by the path to the executable to load on that core.\n");
1549     printf("Options:\n");
1550     printf("  -H <arg>    enable/disable hibernation, 1: ON, 0: OFF,"
1551         " Default: 1)\n");
1552     printf("  -T <arg>    specify the hibernation timeout in ms, Default:"
1553         " 5000 ms)\n");
1554 #else
1555     printf("\n%s: [-gdca] <core_id1> <executable1> [<core_id2> <executable2> ...]\n",
1556         app);
1557     printf("  <core_id#> should be set to a core name (e.g. DSP1, IPU2)\n");
1558     printf("      followed by the path to the executable to load on that core.\n");
1559     printf("Options:\n");
1560     printf("  -g   enable GateMP support on host\n");
1561 #endif
1562     printf("  -d   disable recovery\n");
1563     printf("  -c <file>   generate dump of slave trace during crashes (use\n");
1564     printf("              absolute path for filename)\n");
1565     printf("  -a<n> specify that the first n cores have been pre-loaded\n");
1566     printf("        and started. Perform late-attach to these cores.\n");
1568     exit (EXIT_SUCCESS);
1571 dispatch_t * syslink_dpp = NULL;
1573 int main(int argc, char *argv[])
1575     syslink_dev_t * dev = NULL;
1576     thread_pool_attr_t tattr;
1577     int status;
1578     int error = EOK;
1579     sigset_t set;
1580     int channelid = 0;
1581     int c;
1582     int hib_enable = 1;
1583     uint32_t hib_timeout = PM_HIB_DEFAULT_TIME;
1584     char *user_parm = NULL;
1585     struct stat          sbuf;
1586     int i = 0;
1587     char * abs_path = NULL;
1589     if (-1 != stat(IPC_DEVICE_PATH, &sbuf)) {
1590         printf ("IPC Already Running...\n");
1591         return EXIT_FAILURE;
1592     }
1593     printf ("Starting IPC resource manager...\n");
1595     /* Parse the input args */
1596     while (1)
1597     {
1598         c = getopt (argc, argv, "H:T:U:gc:dv:a:");
1599         if (c == -1)
1600             break;
1602         switch (c)
1603         {
1604 #if defined(SYSLINK_PLATFORM_OMAP5430)
1605         case 'H':
1606             hib_enable = atoi(optarg);
1607             if (hib_enable != 0 && hib_enable != 1) {
1608                 hib_enable = -1;
1609             }
1610             break;
1611         case 'T':
1612             hib_timeout = atoi(optarg);
1613             break;
1614 #endif
1615         case 'U':
1616             user_parm = optarg;
1617             break;
1618         case 'd':
1619             disableRecovery = true;
1620             break;
1621         case 'c':
1622             logFilename = optarg;
1623             break;
1624         case 'a':
1625             numAttach = atoi(optarg);
1626             printf("Late-attaching to %d core(s)\n", numAttach);
1627             break;
1628         case 'v':
1629             verbosity++;
1630             break;
1631 #if defined(SYSLINK_PLATFORM_VAYU)
1632         case 'g':
1633             printf("GateMP support enabled on host\n");
1634             gatempEnabled = true;
1635             break;
1636 #endif
1637         default:
1638             fprintf (stderr, "Unrecognized argument\n");
1639         }
1640     }
1642     /* Now parse the operands, which should be in the format:
1643      * "<multiproc_name> <firmware_file> ..*/
1644     for (; optind + 1 < argc; optind+=2) {
1645         if (syslink_num_cores == MultiProc_MAXPROCESSORS) {
1646             printUsage(argv[0]);
1647             return (error);
1648         }
1649         if (strcmp(argv[optind], INVALID_PROC) == 0) {
1650             fprintf (stderr, "Unsupported core specified\n");
1651             return (error);
1652         }
1654         syslink_firmware[syslink_num_cores].proc = argv [optind];
1655         syslink_firmware[syslink_num_cores].attachOnly =
1656             ((numAttach-- > 0) ? true : false);
1657         syslink_firmware[syslink_num_cores].reload = true;
1658         syslink_firmware[syslink_num_cores].freeString = false;
1659         syslink_firmware[syslink_num_cores++].firmware = argv [optind+1];
1660     }
1662     /* Validate hib_enable args */
1663     if (hib_enable == -1) {
1664         fprintf (stderr, "invalid hibernation enable value\n");
1665         printUsage(argv[0]);
1666         return (error);
1667     }
1669     syslink_hib_enable = (Bool)hib_enable;
1670     syslink_hib_timeout = hib_timeout;
1672     /* Init logging for syslink */
1673     if (Osal_initlogging(verbosity) != 0) {
1674         return -1;
1675     }
1677     /* Obtain I/O privity */
1678     error = ThreadCtl_r (_NTO_TCTL_IO, 0);
1679     if (error == -1) {
1680         Osal_printf("Unable to obtain I/O privity");
1681         return (error);
1682     }
1684     /* Get the abs path for all firmware files */
1685     for (i = 0; i < syslink_num_cores; i++) {
1686         abs_path = calloc(1, PATH_MAX + 1);
1687         if (abs_path == NULL) {
1688             return -1;
1689         }
1690         if (NULL == realpath(syslink_firmware[i].firmware, abs_path)) {
1691             fprintf (stderr, "invalid path to executable\n");
1692             return -1;
1693         }
1694         syslink_firmware[i].firmware = abs_path;
1695     }
1697     /* allocate the device structure */
1698     if (NULL == (dev = calloc(1, sizeof(syslink_dev_t)))) {
1699         Osal_printf("IPC: calloc() failed");
1700         return (-1);
1701     }
1703     /* create the channel */
1704     if ((channelid = ChannelCreate_r (_NTO_CHF_UNBLOCK |
1705                                     _NTO_CHF_DISCONNECT |
1706                                     _NTO_CHF_COID_DISCONNECT |
1707                                     _NTO_CHF_REPLY_LEN |
1708                                     _NTO_CHF_SENDER_LEN)) < 0) {
1709         Osal_printf("Unable to create channel %d", channelid);
1710         return (channelid);
1711     }
1713     /* create the dispatch structure */
1714     if (NULL == (dev->dpp = syslink_dpp = dispatch_create_channel (channelid, 0))) {
1715         Osal_printf("IPC: dispatch_create() failed");
1716         return(-1);
1717     }
1719     /*
1720      * Mask out all signals before creating a thread pool.
1721      * This prevents other threads in the thread pool
1722      * from intercepting signals such as SIGTERM.
1723      */
1724     sigfillset(&set);
1725     pthread_sigmask(SIG_BLOCK, &set, NULL);
1727     /* Initialize the thread pool */
1728     memset (&tattr, 0x00, sizeof (thread_pool_attr_t));
1729     tattr.handle = dev->dpp;
1730     tattr.context_alloc = dispatch_context_alloc;
1731     tattr.context_free = dispatch_context_free;
1732     tattr.block_func = dispatch_block;
1733     tattr.unblock_func = dispatch_unblock;
1734     tattr.handler_func = dispatch_handler;
1735     tattr.lo_water = 2;
1736     tattr.hi_water = 4;
1737     tattr.increment = 1;
1738     tattr.maximum = 10;
1740     /* Create the thread pool */
1741     if ((dev->tpool = thread_pool_create(&tattr, 0)) == NULL) {
1742         Osal_printf("IPC: thread pool create failed");
1743         return(-1);
1744     }
1746     /* init syslink */
1747     status = init_ipc(dev, syslink_firmware, FALSE);
1748     if (status < 0) {
1749         Osal_printf("IPC: init failed");
1750         return(-1);
1751     }
1753     /* init the syslink device */
1754     status = init_devices(dev);
1755     if (status < 0) {
1756         Osal_printf("IPC: device init failed");
1757         return(-1);
1758     }
1760 #if (_NTO_VERSION >= 800)
1761     /* Relinquish privileges */
1762     status = procmgr_ability(  0,
1763                  DENY_ALL | PROCMGR_AID_SPAWN,
1764                  DENY_ALL | PROCMGR_AID_FORK,
1765                  PROCMGR_ADN_NONROOT | PROCMGR_AOP_ALLOW | PROCMGR_AID_MEM_PEER,
1766                  PROCMGR_ADN_NONROOT | PROCMGR_AOP_ALLOW | PROCMGR_AID_MEM_PHYS,
1767                  PROCMGR_ADN_NONROOT | PROCMGR_AOP_ALLOW | PROCMGR_AID_INTERRUPT,
1768                  PROCMGR_ADN_NONROOT | PROCMGR_AOP_ALLOW | PROCMGR_AID_PATHSPACE,
1769                  PROCMGR_ADN_NONROOT | PROCMGR_AOP_ALLOW | PROCMGR_AID_RSRCDBMGR,
1770                  PROCMGR_ADN_ROOT | PROCMGR_AOP_ALLOW | PROCMGR_AOP_LOCK | PROCMGR_AOP_SUBRANGE | PROCMGR_AID_SETUID,
1771                  (uint64_t)1, (uint64_t)~0,
1772                  PROCMGR_ADN_ROOT | PROCMGR_AOP_ALLOW | PROCMGR_AOP_LOCK | PROCMGR_AOP_SUBRANGE | PROCMGR_AID_SETGID,
1773                  (uint64_t)1, (uint64_t)~0,
1774                  PROCMGR_ADN_ROOT | PROCMGR_AOP_DENY | PROCMGR_AOP_LOCK | PROCMGR_AID_EOL);
1776     if (status != EOK) {
1777         Osal_printf("procmgr_ability failed! errno=%d", status);
1778         return EXIT_FAILURE;
1779     }
1781     /* Reduce priority to either what defined from command line or at least nobody */
1782     if (user_parm != NULL) {
1783         if (set_ids_from_arg(user_parm) < 0) {
1784             Osal_printf("unable to set uid/gid - %s", strerror(errno));
1785             return EXIT_FAILURE;
1786         }
1787     } else {
1788         if (setuid(99) != 0) {
1789             Osal_printf("unable to set uid - %s", strerror(errno));
1790             return EXIT_FAILURE;
1791         }
1792     }
1793 #endif
1795     /* make this a daemon process */
1796     if (-1 == procmgr_daemon(EXIT_SUCCESS,
1797         PROCMGR_DAEMON_NOCLOSE | PROCMGR_DAEMON_NODEVNULL)) {
1798         Osal_printf("IPC: procmgr_daemon() failed");
1799         return(-1);
1800     }
1802     /* start the thread pool */
1803     thread_pool_start(dev->tpool);
1805     /* Unmask signals to be caught */
1806     sigdelset (&set, SIGINT);
1807     sigdelset (&set, SIGTERM);
1808     pthread_sigmask (SIG_BLOCK, &set, NULL);
1810     /* Wait for one of these signals */
1811     sigemptyset (&set);
1812     sigaddset (&set, SIGINT);
1813     sigaddset (&set, SIGQUIT);
1814     sigaddset (&set, SIGTERM);
1816     Osal_printf("IPC resource manager started");
1818     /* Wait for a signal */
1819     while (1)
1820     {
1821         switch (SignalWaitinfo (&set, NULL))
1822         {
1823             case SIGTERM:
1824             case SIGQUIT:
1825             case SIGINT:
1826                 error = EOK;
1827                 goto done;
1829             default:
1830                 break;
1831         }
1832     }
1834     error = EOK;
1836 done:
1837     GT_0trace(curTrace, GT_4CLASS, "IPC resource manager exiting \n");
1839     error = thread_pool_destroy(dev->tpool);
1840     if (error < 0) {
1841         Osal_printf("IPC: thread_pool_destroy returned an error");
1842     }
1843     deinit_ipc(dev, syslink_firmware, FALSE);
1844     deinit_devices(dev);
1845     free(dev);
1847     /* Free the abs path of firmware files if necessary */
1848     for (i = 0; i < syslink_num_cores; i++) {
1849         if ((syslink_firmware[i].freeString) &&
1850             (syslink_firmware[i].firmware)) {
1851             free(syslink_firmware[i].firmware);
1852         }
1853     }
1855     return (error);