summaryrefslogtreecommitdiff
path: root/mobicore/rootpa/Code/Common/commandhandler.c
diff options
context:
space:
mode:
Diffstat (limited to 'mobicore/rootpa/Code/Common/commandhandler.c')
-rw-r--r--mobicore/rootpa/Code/Common/commandhandler.c257
1 files changed, 159 insertions, 98 deletions
diff --git a/mobicore/rootpa/Code/Common/commandhandler.c b/mobicore/rootpa/Code/Common/commandhandler.c
index 6d6158c..44da5bc 100644
--- a/mobicore/rootpa/Code/Common/commandhandler.c
+++ b/mobicore/rootpa/Code/Common/commandhandler.c
@@ -3,41 +3,47 @@ Copyright © Trustonic Limited 2013
All rights reserved.
-Redistribution and use in source and binary forms, with or without modification,
+Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
- 1. Redistributions of source code must retain the above copyright notice, this
+ 1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
- 2. Redistributions in binary form must reproduce the above copyright notice,
- this list of conditions and the following disclaimer in the documentation
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
- 3. Neither the name of the Trustonic Limited nor the names of its contributors
- may be used to endorse or promote products derived from this software
+ 3. Neither the name of the Trustonic Limited nor the names of its contributors
+ may be used to endorse or promote products derived from this software
without specific prior written permission.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
-ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
-IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
-INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
-BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
-LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
-OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <string.h>
#include <stdlib.h>
-#include <pthread.h>
+
+#include <wrapper.h>
+#ifdef WIN32
+ #include <windows.h>
+#else
+ #include <pthread.h>
+#endif
#include <TlCm/3.0/tlCmApi.h>
#include <MobiCoreDriverApi.h>
#include "rootpaErrors.h"
#include "logging.h"
-#include "provisioningagent.h"
+#include "provisioningagent.h"
#include "registry.h"
#include "contentmanager.h"
#include "provisioningengine.h"
@@ -51,12 +57,10 @@ OF THE POSSIBILITY OF SUCH DAMAGE.
/*
See provisioningagent.h for description of this function.
*/
-
rootpaerror_t executeCmpCommands(int numberOfCommands, CmpMessage* commandsP, CmpMessage* responsesP, uint32_t* internalError)
-{
- LOGD(">>executeCmpCommands");
+{
+ LOGD("executeCmpCommands");
return executeContentManagementCommands(numberOfCommands, commandsP, responsesP, internalError);
- LOGD("<<executeCmpCommands");
}
rootpaerror_t openSessionToCmtl()
@@ -71,32 +75,32 @@ void closeSessionToCmtl()
rootpaerror_t getVersion(int* tag, mcVersionInfo_t* versionP)
{
- LOGD(">>getVersion");
rootpaerror_t ret=ROOTPA_OK;
- uint32_t internalError=0;
- CmpMessage command;
+ uint32_t internalError=0;
+ CmpMessage command;
CmpMessage response;
+ LOGD(">>getVersion");
memset(&command,0,sizeof(CmpMessage));
memset(&response,0,sizeof(CmpMessage));
-
+
command.length=GET_VERSION_COMMAND_LENGTH;
- command.contentP=malloc(GET_VERSION_COMMAND_LENGTH);
+ command.contentP=(uint8_t*)malloc(GET_VERSION_COMMAND_LENGTH);
if(!command.contentP)
{
return ROOTPA_ERROR_OUT_OF_MEMORY;
}
-
+
*((uint32_t*)command.contentP)=MC_CMP_CMD_GET_VERSION;
command.hdr.ignoreError=false;
-
+
ret=executeContentManagementCommands(1, &command, &response, &internalError);
if(ROOTPA_OK==ret && 0 == internalError)
{
if(response.length != sizeof(cmpRspGetVersion_t))
{
- ret=ROOTPA_ERROR_INTERNAL;
+ ret=ROOTPA_ERROR_INTERNAL;
}
else
{
@@ -115,7 +119,7 @@ rootpaerror_t getVersion(int* tag, mcVersionInfo_t* versionP)
}
else
{
- LOGE("getVersion, ERROR %d %d", ret, internalError);
+ LOGE("getVersion, ERROR %d %d", ret, internalError);
}
free(response.contentP);
free(command.contentP);
@@ -125,32 +129,32 @@ rootpaerror_t getVersion(int* tag, mcVersionInfo_t* versionP)
rootpaerror_t getSuid(mcSuid_t* suidP)
{
- LOGD(">>getSuid");
rootpaerror_t ret=ROOTPA_OK;
- uint32_t internalError=0;
- CmpMessage command;
+ uint32_t internalError=0;
+ CmpMessage command;
CmpMessage response;
-
+
+ LOGD(">>getSuid");
memset(&command,0,sizeof(CmpMessage));
memset(&response,0,sizeof(CmpMessage));
-
+
command.length=GET_SUID_COMMAND_LENGTH;
- command.contentP=malloc(GET_SUID_COMMAND_LENGTH);
+ command.contentP=(uint8_t*)malloc(GET_SUID_COMMAND_LENGTH);
if(!command.contentP)
{
return ROOTPA_ERROR_OUT_OF_MEMORY;
}
-
+
*((uint32_t*)command.contentP)=MC_CMP_CMD_GET_SUID;
command.hdr.ignoreError=false;
-
+
ret=executeContentManagementCommands(1, &command, &response, &internalError);
if(ROOTPA_OK==ret && 0 == internalError)
{
if(response.length != sizeof(cmpRspGetSuid_t))
{
- ret=ROOTPA_ERROR_INTERNAL;
+ ret=ROOTPA_ERROR_INTERNAL;
}
else
{
@@ -165,36 +169,36 @@ rootpaerror_t getSuid(mcSuid_t* suidP)
rootpaerror_t isRootContainerRegistered(bool* isRegisteredP)
{
- LOGD(">>isRootContainerRegistered");
rootpaerror_t ret=ROOTPA_OK;
-
- if(NULL==isRegisteredP) return ROOTPA_ERROR_ILLEGAL_ARGUMENT;
-
ROOTCONTAINERP rootContP=NULL;
uint32_t rootContSize=0;
- mcResult_t result=regReadRoot(&rootContP, &rootContSize);
+ mcResult_t result;
+ LOGD(">>isRootContainerRegistered");
+ if(NULL==isRegisteredP) return ROOTPA_ERROR_ILLEGAL_ARGUMENT;
+
+ result=regReadRoot(&rootContP, &rootContSize);
if(MC_DRV_OK == result)
{
if(rootContP->cont.attribs.state != MC_CONT_STATE_UNREGISTERED)
{
*isRegisteredP=true;
- }
+ }
else
{
- *isRegisteredP=false;
+ *isRegisteredP=false;
}
-
+
}
else if(MC_DRV_ERR_INVALID_DEVICE_FILE == result)
{
- *isRegisteredP=false;
+ *isRegisteredP=false;
}
else
{
ret=ROOTPA_ERROR_REGISTRY;
}
-
+
free(rootContP);
LOGD("<<isRootContainerRegistered %d", *isRegisteredP);
@@ -203,14 +207,14 @@ rootpaerror_t isRootContainerRegistered(bool* isRegisteredP)
rootpaerror_t isSpContainerRegistered(mcSpid_t spid, bool* isRegisteredP)
{
- LOGD(">>isSpContainerRegistered");
rootpaerror_t ret=ROOTPA_OK;
+ int state;
+ LOGD(">>isSpContainerRegistered");
if(NULL==isRegisteredP) return ROOTPA_ERROR_ILLEGAL_ARGUMENT;
- int state;
- ret=getSpContainerState(spid, &state);
-
+ ret=getSpContainerState(spid, (mcContainerState_t*)&state);
+
if(ROOTPA_OK == ret)
{
if(state != MC_CONT_STATE_UNREGISTERED)
@@ -219,7 +223,7 @@ rootpaerror_t isSpContainerRegistered(mcSpid_t spid, bool* isRegisteredP)
}
else
{
- *isRegisteredP=false;
+ *isRegisteredP=false;
}
}
else if(ROOTPA_ERROR_INTERNAL_NO_CONTAINER == ret)
@@ -227,7 +231,7 @@ rootpaerror_t isSpContainerRegistered(mcSpid_t spid, bool* isRegisteredP)
*isRegisteredP=false;
ret=ROOTPA_OK;
}
-
+
LOGD("<<isSpContainerRegistered %d", *isRegisteredP);
return ret;
}
@@ -235,13 +239,14 @@ rootpaerror_t isSpContainerRegistered(mcSpid_t spid, bool* isRegisteredP)
rootpaerror_t getSpContainerState(mcSpid_t spid, mcContainerState_t* stateP)
{
- LOGD(">>getSpContainerState");
rootpaerror_t ret=ROOTPA_OK;
+ mcResult_t result;
+ LOGD(">>getSpContainerState");
if(NULL==stateP) return ROOTPA_ERROR_ILLEGAL_ARGUMENT;
- mcResult_t result=regGetSpState(spid, stateP);
-
+ result=regGetSpState(spid, stateP);
+
if(MC_DRV_ERR_INVALID_DEVICE_FILE == result)
{
ret=ROOTPA_ERROR_INTERNAL_NO_CONTAINER; // using this since it is changed to ROOTPA_OK and state NO_CONTAINER in the wrapper.
@@ -262,29 +267,30 @@ bool containerExists(mcUuid_t uuid)
rootpaerror_t getSpContainerStructure(mcSpid_t spid, SpContainerStructure* spContainerStructure)
{
- LOGD(">>getSpContainerStructure");
rootpaerror_t ret=ROOTPA_OK;
-
+ SPCONTAINERP spP=NULL;
+ uint32_t spContSize=0;
+ mcResult_t result;
+ int i;
+ TLTCONTAINERP tltP=NULL;
+ LOGD(">>getSpContainerStructure");
+
if(NULL==spContainerStructure) return ROOTPA_ERROR_ILLEGAL_ARGUMENT;
memset(spContainerStructure, 0xFF, sizeof(SpContainerStructure));
- spContainerStructure->nbrOfTlts=0;
-
- SPCONTAINERP spP=NULL;
- uint32_t spContSize=0;
- mcResult_t result=regReadSp(spid, &spP, &spContSize);
+ spContainerStructure->nbrOfTlts=0;
+ result=regReadSp(spid, &spP, &spContSize);
+
if(MC_DRV_OK == result)
{
spContainerStructure->state=spP->cont.attribs.state;
- int i;
-
for(i=0; i<MC_CONT_CHILDREN_COUNT; i++)
{
if(containerExists(spP->cont.children[i]))
{
memcpy(&spContainerStructure->tltContainers[spContainerStructure->nbrOfTlts].uuid, &(spP->cont.children[i]), sizeof(mcUuid_t));
- TLTCONTAINERP tltP=NULL;
+
if(ROOTPA_OK == ret)
{
uint32_t tltContSize=0;
@@ -309,16 +315,48 @@ rootpaerror_t getSpContainerStructure(mcSpid_t spid, SpContainerStructure* spCo
{
ret=ROOTPA_ERROR_INTERNAL_NO_CONTAINER; // using this since it is changed to ROOTPA_OK and state NO_CONTAINER in the wrapper.
}
- else
+ else
{
ret=ROOTPA_ERROR_REGISTRY;
}
-
+
free(spP);
LOGD("<<getSpContainerStructure nr: %d st: %d ret: %d",spContainerStructure->nbrOfTlts, spContainerStructure->state, ret );
return ret;
}
+rootpaerror_t storeTA(mcSpid_t spid, const mcUuid_t* uuidP, const uint8_t* taBinP, uint32_t taBinLength)
+{
+ rootpaerror_t ret=ROOTPA_OK;
+ mcResult_t result=0;
+ mcContainerState_t state;
+
+ result=regGetTaState(spid, uuidP, &state);
+ LOGD("storeTA, TA state %d, result 0x%x", state, result);
+ if(MC_DRV_ERR_INVALID_DEVICE_FILE == result)
+ {
+ LOGW("storeTA, not storing, since TA container is missing");
+ ret=ROOTPA_ERROR_ILLEGAL_ARGUMENT;
+ }
+ else if (result!=MC_DRV_OK)
+ {
+ LOGW("storeTA, not storing, due to TA container read error 0x%x", result);
+ ret=ROOTPA_ERROR_REGISTRY;
+ }
+ else
+ {
+ result =regStoreTA(spid, uuidP, taBinP, taBinLength);
+
+ if(result != MC_DRV_OK)
+ {
+ LOGE("storeTA, storing TA failed, result from registry 0x%x", result);
+ ret=ROOTPA_ERROR_REGISTRY;
+ }
+ }
+
+ return ret;
+}
+
void dummyCallback(ProvisioningState state, rootpaerror_t error, tltInfo_t* tltInfoP)
{
LOGD("dummy callback %d %d %ld", state, error, (long int) tltInfoP);
@@ -327,7 +365,7 @@ void dummyCallback(ProvisioningState state, rootpaerror_t error, tltInfo_t* tltI
rootpaerror_t dummySysInfoCallback(osInfo_t* osSpecificInfoP)
{
LOGD("dummy sysinfo callback %ld", (long int) osSpecificInfoP);
- if(NULL==osSpecificInfoP) return ROOTPA_ERROR_INTERNAL;
+ if(NULL==osSpecificInfoP) return ROOTPA_ERROR_INTERNAL;
memset(osSpecificInfoP, 0, sizeof(osInfo_t));
return ROOTPA_OK;
}
@@ -340,17 +378,19 @@ typedef struct{
initialRel_t initialRel;
trustletInstallationData_t* tltInstallationDataP;
} provisioningparams_t;
-
-void* provisioningThreadFunction(void* paramsP)
+#ifdef WIN32
+ void* WINAPI provisioningThreadFunction(void* paramsP)
+#else
+ void* provisioningThreadFunction(void* paramsP)
+#endif
{
- LOGD(">>provisioningThreadFunction %ld", (long int)((provisioningparams_t*)paramsP)->callbackP);
-
rootpaerror_t ret=ROOTPA_OK;
+ LOGD(">>provisioningThreadFunction %ld", (long int)((provisioningparams_t*)paramsP)->callbackP);
if((ret=openCmtlSession())==ROOTPA_OK)
{
- doProvisioningWithSe(((provisioningparams_t*)paramsP)->spid,
- ((provisioningparams_t*)paramsP)->suid,
- ((provisioningparams_t*)paramsP)->callbackP,
+ doProvisioningWithSe(((provisioningparams_t*)paramsP)->spid,
+ ((provisioningparams_t*)paramsP)->suid,
+ ((provisioningparams_t*)paramsP)->callbackP,
((provisioningparams_t*)paramsP)->sysInfoCallbackP,
getVersion,
((provisioningparams_t*)paramsP)->initialRel,
@@ -359,7 +399,7 @@ void* provisioningThreadFunction(void* paramsP)
}
else
{
- ((provisioningparams_t*)paramsP)->callbackP(ERROR, ret, NULL);
+ ((provisioningparams_t*)paramsP)->callbackP(ERROR_STATE, ret, NULL);
LOGE("provisioningThreadFunction: was not able to open session %d", ret);
}
@@ -373,29 +413,39 @@ void* provisioningThreadFunction(void* paramsP)
free(paramsP); // Coverity complains that paramsP allocated in "provisioning" is not freed. It is done here.
LOGD("<<provisioningThreadFunction");
+#ifdef WIN32
+ ExitThread(NULL);
+#else
pthread_exit(NULL);
+#endif
return NULL; // this is required by some compilers with some settings in order to avoid errors.
}
rootpaerror_t provision(mcSpid_t spid, CallbackFunctionP callbackP, SystemInfoCallbackFunctionP systemInfoCallbackP, trustletInstallationData_t* tltDataP, initialRel_t initialRel)
{
+ provisioningparams_t* paramsP;
+ rootpaerror_t ret;
+#ifdef WIN32
+ HANDLE provisioningThread;
+ DWORD threadID;
+#endif
LOGD(">>provision %ld %ld", (long int) callbackP, (long int) dummyCallback);
if(NULL==callbackP) callbackP=dummyCallback;
if(NULL==systemInfoCallbackP) systemInfoCallbackP=dummySysInfoCallback;
- provisioningparams_t* paramsP=malloc(sizeof(provisioningparams_t));
+ paramsP=(provisioningparams_t*)malloc(sizeof(provisioningparams_t));
if(!paramsP) return ROOTPA_ERROR_OUT_OF_MEMORY;
-
+
memset(paramsP,0,sizeof(provisioningparams_t)); // initialize in order to satisfy valgrind
-
+
paramsP->callbackP=callbackP;
paramsP->sysInfoCallbackP=systemInfoCallbackP;
paramsP->spid=spid;
if(tltDataP)
{
- // Coverity complains that paramsP allocated here is not freed. It is done in "provisioningThreadFunction"
- paramsP->tltInstallationDataP=malloc(sizeof(trustletInstallationData_t));
+ // Coverity complains that paramsP allocated here is not freed. It is done in "provisioningThreadFunction"
+ paramsP->tltInstallationDataP=(trustletInstallationData_t*)malloc(sizeof(trustletInstallationData_t));
if(!paramsP->tltInstallationDataP)
{
free(paramsP);
@@ -403,13 +453,13 @@ rootpaerror_t provision(mcSpid_t spid, CallbackFunctionP callbackP, SystemInfoCa
}
// copy the whole struct
-
+
memset(paramsP->tltInstallationDataP,0,sizeof(trustletInstallationData_t)); // initialize in order to satisfy valgrind
memcpy(paramsP->tltInstallationDataP, tltDataP, sizeof(trustletInstallationData_t));
// malloc and copy data from/to the pointers
-
- paramsP->tltInstallationDataP->dataP=malloc(tltDataP->dataLength);
+
+ paramsP->tltInstallationDataP->dataP=(const uint8_t *)malloc(tltDataP->dataLength);
if(!paramsP->tltInstallationDataP->dataP)
{
free(paramsP->tltInstallationDataP);
@@ -419,30 +469,39 @@ rootpaerror_t provision(mcSpid_t spid, CallbackFunctionP callbackP, SystemInfoCa
memset((char*)paramsP->tltInstallationDataP->dataP,0,tltDataP->dataLength); // initialize in order to satisfy valgrind
memcpy((char*)paramsP->tltInstallationDataP->dataP, tltDataP->dataP, tltDataP->dataLength);
- paramsP->tltInstallationDataP->tltPukHashP=malloc(tltDataP->tltPukHashLength);
+ paramsP->tltInstallationDataP->tltPukHashP=(const uint8_t *)malloc(tltDataP->tltPukHashLength);
if(!paramsP->tltInstallationDataP->tltPukHashP)
{
free((void*) paramsP->tltInstallationDataP->dataP);
free((void*) paramsP->tltInstallationDataP);
free(paramsP);
return ROOTPA_ERROR_OUT_OF_MEMORY;
- }
+ }
memset((char*)paramsP->tltInstallationDataP->tltPukHashP,0,tltDataP->tltPukHashLength); // initialize in order to satisfy valgrind
memcpy((char*)paramsP->tltInstallationDataP->tltPukHashP, tltDataP->tltPukHashP, tltDataP->tltPukHashLength);
}
else
{
- paramsP->tltInstallationDataP=NULL;
+ paramsP->tltInstallationDataP=NULL;
}
paramsP->initialRel = initialRel;
-
- rootpaerror_t ret=ROOTPA_OK;
+
+ ret=ROOTPA_OK;
ret=getSuid(&paramsP->suid);
if(ROOTPA_OK==ret)
{
+#ifdef WIN32
+ provisioningThread = CreateThread( NULL, 0, (LPTHREAD_START_ROUTINE)provisioningThreadFunction, (void*) paramsP, 0, &threadID);
+
+ if (provisioningThread == NULL)
+ {
+ LOGE("unable to create thread");
+ ret=ROOTPA_ERROR_INTERNAL;
+ }
+#else
pthread_t provisioningThread;
pthread_attr_t attributes;
int r=0;
@@ -453,13 +512,13 @@ rootpaerror_t provision(mcSpid_t spid, CallbackFunctionP callbackP, SystemInfoCa
ret=ROOTPA_ERROR_INTERNAL;
}
else
- {
+ {
r=pthread_attr_setdetachstate(&attributes, PTHREAD_CREATE_DETACHED);
if(r)
{
LOGE("unable to set detached state, trying with defaults %d",r);
}
-
+
r=pthread_create(&provisioningThread, &attributes, provisioningThreadFunction, (void*) paramsP);
if(r)
{
@@ -469,10 +528,11 @@ rootpaerror_t provision(mcSpid_t spid, CallbackFunctionP callbackP, SystemInfoCa
}
pthread_attr_destroy(&attributes);
}
+#endif
}
else
{
- LOGE("provisioning can not get suid: %d",ret );
+ LOGE("provisioning can not get suid: %d",ret );
}
LOGD("<<provision ret: %d",ret );
return ret;
@@ -486,7 +546,7 @@ rootpaerror_t doProvisioning(mcSpid_t spid, CallbackFunctionP callbackP, SystemI
rootpaerror_t installTrustlet(mcSpid_t spid, CallbackFunctionP callbackP, SystemInfoCallbackFunctionP systemInfoCallbackP, trustletInstallationData_t* tltDataP)
{
- if(NULL == tltDataP || NULL == tltDataP->dataP || 0 == tltDataP->dataLength||
+ if(NULL == tltDataP || NULL == tltDataP->dataP || 0 == tltDataP->dataLength||
(REQUEST_DATA_TLT != tltDataP->dataType && REQUEST_DATA_KEY != tltDataP->dataType)) return ROOTPA_ERROR_ILLEGAL_ARGUMENT;
LOGD("installTrustlet");
return provision(spid, callbackP, systemInfoCallbackP, tltDataP, initialRel_POST);
@@ -505,9 +565,10 @@ void setPaths(const char* storageDirP, const char* certDirP)
rootpaerror_t unregisterRootContainer(CallbackFunctionP callbackP, SystemInfoCallbackFunctionP systemInfoCallbackP)
{
- LOGD("unregisterRootContainer");
-
mcSpid_t spid;
+ LOGD("unregisterRootContainer");
memset(&spid, 0x0, sizeof(mcSpid_t));
return provision(spid, callbackP, systemInfoCallbackP, NULL, initialRel_DELETE);
}
+
+