]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - ipc/ipcdev.git/blobdiff - linux/src/daemon/GateMP_daemon.c
Linux: GateMP: Check for Proper NameServer Value Length
[ipc/ipcdev.git] / linux / src / daemon / GateMP_daemon.c
index d2db25d3bed18809991fd4058ad5ef34ed658f03..56b2ad6dd741eddc75342b9d085e0d94570e9a40 100644 (file)
@@ -47,6 +47,9 @@
 #include <fcntl.h>
 #include <stdlib.h>
 #include <assert.h>
+#include <dirent.h>
+#include <errno.h>
+#include <string.h>
 
 /* Module level headers */
 #include <ti/ipc/GateMP.h>
@@ -74,6 +77,9 @@ extern "C" {
 /* Name of GateMP's nameserver */
 #define GateMP_NAMESERVER  "GateMP"
 
+/* sysfs path for the UIO user-space drivers */
+#define UIO_SYSFS          "/sys/class/uio"
+
 #define PAGE_ALIGN(size, psz)  (((size) + psz - 1) & ~(psz -1))
 
 /* =============================================================================
@@ -92,10 +98,13 @@ typedef struct {
     GateMP_Handle     defaultGate;
     NameServer_Handle nameServer;
     Bool              isSetup;
+    Int               refCount[MultiProc_MAXPROCESSORS];
+    UInt16            attachedProcId;
 } GateMP_ModuleObject;
 
 /* Internal functions */
-static Int GateMP_openDefaultGate(GateMP_Handle *handlePtr);
+static Int GateMP_get_sr0(Char *name, UInt32 name_len, UInt32 *baseaddr);
+static Int GateMP_openDefaultGate(GateMP_Handle *handlePtr, UInt16 procId[]);
 static Int GateMP_closeDefaultGate(GateMP_Handle *handlePtr);
 
 /* =============================================================================
@@ -114,7 +123,9 @@ static GateMP_ModuleObject GateMP_state = {
     .remoteCustom2InUse              = NULL,
     .defaultGate                     = NULL,
     .nameServer                      = NULL,
-    .isSetup                         = FALSE
+    .isSetup                         = FALSE,
+    .refCount                        = {0},
+    .attachedProcId                  = MultiProc_INVALIDID,
 };
 
 static GateMP_ModuleObject * GateMP_module = &GateMP_state;
@@ -124,17 +135,15 @@ static GateMP_ModuleObject * GateMP_module = &GateMP_state;
  * =============================================================================
  */
 
-/* Function to setup the gatemp module. */
+/*
+ * Function to setup the gatemp module.
+ *
+ * No need to refCount this since it's not callable by user.
+ */
 Int GateMP_setup(Void)
 {
     Int               status = GateMP_S_SUCCESS;
     NameServer_Params params;
-    UInt32            nsValue[NUM_INFO_FIELDS];
-    UInt32            len;
-    UInt32            size;
-    UInt32            alignDiff;
-    UInt32            offset;
-    Int32             fdMem;
 
     NameServer_Params_init(&params);
     params.maxRuntimeEntries = MAX_RUNTIME_ENTRIES;
@@ -150,38 +159,88 @@ Int GateMP_setup(Void)
         status = GateMP_E_FAIL;
         LOG0("GateMP_setup: NameServer_create failed\n");
     }
+    else {
+        GateMP_module->isSetup = TRUE;
+    }
 
-    if (status == GateMP_S_SUCCESS) {
-        do {
-            sleep(1);   /* Give the slaves some time to get NameServer ready */
-            status = GateMP_openDefaultGate(&GateMP_module->defaultGate);
-        } while (status == GateMP_E_NOTFOUND);
+    return status;
+}
 
+Int GateMP_attach(UInt16 procId)
+{
+    GateMP_Handle     deflateGate;  /* that's right, Pats fan here */
+    Int               status = GateMP_S_SUCCESS;
+    UInt32            nsValue[NUM_INFO_FIELDS];
+    UInt32            len;
+    UInt32            size;
+    UInt32            alignDiff;
+    UInt32            offset;
+    UInt32            baseaddr;
+    Int32             fdMem;
+    UInt16            procList[2];
+    UInt16            clId;
+    Char              filename[PATH_MAX];
+
+    /* procId already validated in API layer */
+    clId = procId - MultiProc_getBaseIdOfCluster();
+    if (clId >= MultiProc_getNumProcsInCluster()) {
+        LOG1("GateMP_attach: procId %d not in range for local cluster\n",
+             procId);
+        return GateMP_E_INVALIDARG;
+    }
 
-        if (status < 0) {
-            LOG0("GateMP_setup: failed to open default gate\n");
-            status = GateMP_E_FAIL;
-        }
+    /* must reference count because we have multiple clients */
+    if (GateMP_module->refCount[clId] > 0) {
+        GateMP_module->refCount[clId]++;
+        goto done;
+    }
+
+    procList[0] = procId;
+    procList[1] = MultiProc_INVALIDID;
+    status = GateMP_openDefaultGate(&deflateGate, procList);
+
+    if (status < 0) {
+        LOG1("GateMP_attach: failed to open default gate on procId %d\n",
+             procId);
+        goto done;
     }
 
     if (status == GateMP_S_SUCCESS) {
+        if (GateMP_module->attachedProcId != MultiProc_INVALIDID) {
+            LOG1("GateMP_attach: can't attach to procId %d\n", procId);
+            LOG1("               already attached to %d\n",
+                 GateMP_module->attachedProcId);
+            status = GateMP_E_ALREADYEXISTS;
+            goto done;
+        }
+
+        GateMP_module->attachedProcId = procId;
+        GateMP_module->defaultGate = deflateGate;
+
+        GateMP_module->refCount[clId]++;
+
         /* Process global info NameServer entry */
         len = sizeof(nsValue);
 
         status = NameServer_get(GateMP_module->nameServer, "_GateMP_TI_info",
-            &nsValue, &len, NULL);
+            &nsValue, &len, procList);
 
         if (status < 0) {
-            LOG0("GateMP_setup: failed to find info entry\n");
+            LOG0("GateMP_attach: failed to find info entry\n");
             status = GateMP_E_NOTFOUND;
         }
         else {
-            fdMem = open ("/dev/mem", O_RDWR | O_SYNC);
+            status = GateMP_get_sr0(filename, PATH_MAX, &baseaddr);
+            if (status < 0) {
+                LOG1("GateMP_attach: failed to find sr0: %s\n", strerror(status));
+                status = GateMP_E_NOTFOUND;
+            }
 
+            fdMem = open (filename, O_RDWR | O_SYNC);
             if (fdMem < 0){
-                LOG0("GateMP_setup: failed to open the /dev/mem!\n");
-                status = GateMP_E_FAIL;
-                goto cleanup;
+                LOG1("GateMP_attach: failed to open the %s!\n", filename);
+                status = GateMP_E_OSFAILURE;
+                goto done;
             }
 
             GateMP_module->numRemoteSystem = nsValue[3];
@@ -193,6 +252,8 @@ Int GateMP_setup(Void)
                 (nsValue[0] & (sysconf(_SC_PAGE_SIZE) - 1));
             size = PAGE_ALIGN(size, sysconf(_SC_PAGE_SIZE));
             offset = nsValue[0] & ~(sysconf(_SC_PAGE_SIZE) - 1);
+            offset -= baseaddr;
+
 #if defined(IPC_BUILDOS_ANDROID)
             GateMP_module->remoteSystemInUse = mmap64(NULL, size,
                 (PROT_READ|PROT_WRITE), (MAP_SHARED), fdMem,
@@ -209,7 +270,7 @@ Int GateMP_setup(Void)
                  status = GateMP_E_MEMORY;
             }
             else {
-                alignDiff = nsValue[0] - offset;
+                alignDiff = nsValue[0] - baseaddr - offset;
                 GateMP_module->remoteSystemInUse =
                     GateMP_module->remoteSystemInUse + alignDiff;
             }
@@ -218,6 +279,8 @@ Int GateMP_setup(Void)
                 (nsValue[1] & (sysconf(_SC_PAGE_SIZE) - 1));
             size = PAGE_ALIGN(size, sysconf(_SC_PAGE_SIZE));
             offset = nsValue[1] & ~(sysconf(_SC_PAGE_SIZE) - 1);
+            offset -= baseaddr;
+
             if (status == GateMP_S_SUCCESS) {
 #if defined(IPC_BUILDOS_ANDROID)
                 GateMP_module->remoteCustom1InUse = mmap64(NULL, size,
@@ -235,7 +298,7 @@ Int GateMP_setup(Void)
                     status = GateMP_E_MEMORY;
                 }
                 else {
-                    alignDiff = nsValue[1] - offset;
+                    alignDiff = nsValue[1] - baseaddr - offset;
                     GateMP_module->remoteCustom1InUse =
                         GateMP_module->remoteCustom1InUse + alignDiff;
                 }
@@ -245,6 +308,8 @@ Int GateMP_setup(Void)
                 (nsValue[2] & (sysconf(_SC_PAGE_SIZE) - 1));
             size = PAGE_ALIGN(size, sysconf(_SC_PAGE_SIZE));
             offset = nsValue[2] & ~(sysconf(_SC_PAGE_SIZE) - 1);
+            offset -= baseaddr;
+
             if (status == GateMP_S_SUCCESS) {
 #if defined(IPC_BUILDOS_ANDROID)
                 GateMP_module->remoteCustom2InUse = mmap64(NULL, size,
@@ -262,7 +327,7 @@ Int GateMP_setup(Void)
                     status = GateMP_E_MEMORY;
                 }
                 else {
-                    alignDiff = nsValue[2] - offset;
+                    alignDiff = nsValue[2] - baseaddr - offset;
                     GateMP_module->remoteCustom2InUse =
                         GateMP_module->remoteCustom2InUse + alignDiff;
                 }
@@ -272,19 +337,33 @@ Int GateMP_setup(Void)
 
     /* TODO: setup the proxy map */
 
-cleanup:
-    /* clean up if error */
-    if (status < 0) {
-        GateMP_destroy();
-    }
-
-    GateMP_module->isSetup = TRUE;
+done:
 
     return (status);
 }
 
-Void GateMP_destroy(Void)
+Int GateMP_detach(UInt16 procId)
 {
+    UInt16 clId;
+
+    if (procId != GateMP_module->attachedProcId) {
+        return GateMP_E_NOTFOUND;
+    }
+
+    /* procId already validated in API layer */
+    clId = procId - MultiProc_getBaseIdOfCluster();
+    if (clId >= MultiProc_getNumProcsInCluster()) {
+        LOG1("GateMP_detach: procId %d not in range for local cluster\n",
+             procId);
+        return GateMP_E_INVALIDARG;
+    }
+
+
+    /* decrement reference count regardless of outcome below */
+    if (--GateMP_module->refCount[clId] > 0) {
+        goto done;
+    }
+
     if (GateMP_module->remoteSystemInUse) {
         munmap((unsigned int *)GateMP_module->remoteSystemInUse,
             GateMP_module->numRemoteSystem * sizeof (UInt8));
@@ -305,8 +384,16 @@ Void GateMP_destroy(Void)
 
     if (GateMP_module->defaultGate) {
         GateMP_closeDefaultGate(&GateMP_module->defaultGate);
+        GateMP_module->attachedProcId = MultiProc_INVALIDID;
     }
 
+done:
+
+    return GateMP_S_SUCCESS;
+}
+
+Void GateMP_destroy(Void)
+{
     if (GateMP_module->nameServer) {
         NameServer_delete(&GateMP_module->nameServer);
         GateMP_module->nameServer = NULL;
@@ -317,8 +404,89 @@ Void GateMP_destroy(Void)
     return;
 }
 
-/* Open default gate during GateMP_setup. Should only be called once */
-static Int GateMP_openDefaultGate(GateMP_Handle *handlePtr)
+static Int GateMP_get_sr0(Char *name, UInt32 name_len, UInt32 *baseaddr)
+{
+    Char filename[PATH_MAX];
+    Char format[80];
+    Char uio_name[80];
+    DIR *dir;
+    struct dirent *de;
+    struct stat st;
+    FILE *fd;
+    Bool found = false;
+    Int ret = 0;
+
+    if (stat(UIO_SYSFS, &st) < 0) {
+        if ((errno == ENOENT) || (errno == ENOTDIR)) {
+            LOG0("GateMP_get_sr0: UIO support not found\n");
+            ret = errno;
+            goto out;
+        }
+    }
+
+    dir = opendir(UIO_SYSFS);
+    if (!dir) {
+        LOG1("GateMP_get_sr0: failed to open UIO sysfs %s\n", UIO_SYSFS);
+        ret = errno;
+        goto out;
+    }
+
+    while (!found) {
+        de = readdir(dir);
+        if (!de) {
+            break;
+        }
+
+        if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, "..")) {
+            continue;
+        }
+
+        /* Skip if this is not an UIO entry */
+        snprintf(filename, sizeof(filename), "%s/%s/name", UIO_SYSFS, de->d_name);
+        fd = fopen(filename, "r");
+        if (fd == NULL) {
+            continue;
+        }
+
+        snprintf(format, sizeof(format), "%%%ds", sizeof(uio_name)-1);
+        fscanf(fd, format, uio_name);
+        fclose(fd);
+
+        /* Skip if this UIO entry is not SR0 */
+        if (strncmp(uio_name, "sr0", sizeof(uio_name)-1)) {
+            continue;
+        }
+
+        /* Find the base address of the SR0 UIO */
+        snprintf(filename, sizeof(filename), "%s/%s/maps/map0/addr", UIO_SYSFS, de->d_name);
+        fd = fopen(filename, "r");
+        if (fd == NULL) {
+            LOG0("Gate_sr0_filename: failed to open uio map sysfs\n");
+            ret = errno;
+            break;
+        }
+
+        fscanf(fd, "0x%x", baseaddr);
+        fclose(fd);
+
+        snprintf(name, name_len, "/dev/%s", de->d_name);
+        found = true;
+    }
+
+    closedir(dir);
+
+out:
+    /* Fall back to /dev/mem if UIO is not supported */
+    if (!found) {
+        strncpy(name, "/dev/mem", name_len);
+        *baseaddr = 0x0;
+    }
+
+    return ret;
+}
+
+/* Open default gate during GateMP_attach. Should only be called once */
+static Int GateMP_openDefaultGate(GateMP_Handle *handlePtr, UInt16 procId[])
 {
     Int             status = GateMP_S_SUCCESS;
     UInt32          len;
@@ -326,13 +494,12 @@ static Int GateMP_openDefaultGate(GateMP_Handle *handlePtr)
     GateMP_Object * obj = NULL;
     UInt32          arg;
     UInt32          mask;
-    UInt32          creatorProcId;
 
     GateMP_RemoteSystemProxy_Params     systemParams;
 
     /* assert that a valid pointer has been supplied */
     if (handlePtr == NULL) {
-        LOG0("GateMP_open: argument cannot be null\n");
+        LOG0("GateMP_openDefaultGate: argument cannot be null\n");
         status = GateMP_E_INVALIDARG;
     }
 
@@ -340,16 +507,21 @@ static Int GateMP_openDefaultGate(GateMP_Handle *handlePtr)
         len = sizeof(nsValue);
 
         status = NameServer_get(GateMP_module->nameServer, "_GateMP_TI_dGate",
-            &nsValue, &len, NULL);
+            &nsValue, &len, procId);
 
         if (status < 0) {
             *handlePtr = NULL;
             status = GateMP_E_NOTFOUND;
         }
+        else if (len != sizeof(nsValue)) {
+            *handlePtr = NULL;
+            status = GateMP_E_NOTFOUND;
+            LOG0("GateMP configuration not valid for hostSupport. "
+                 "Try adding hostSupport to your config if it is needed.\n");
+        }
         else {
             arg = nsValue[2];
             mask = nsValue[3];
-            creatorProcId = nsValue[1] >> 16;
         }
     }