Added pre-main capabilities, cleaned up services and NameServer modules
[keystone-rtos/rm-lld.git] / src / rm_services.c
1 /**
2  *   @file  rmservices.c
3  *
4  *   @brief   
5  *      This is the Resource Manager services source.
6  *
7  *  \par
8  *  ============================================================================
9  *  @n   (C) Copyright 2012, Texas Instruments, Inc.
10  * 
11  *  Redistribution and use in source and binary forms, with or without 
12  *  modification, are permitted provided that the following conditions 
13  *  are met:
14  *
15  *    Redistributions of source code must retain the above copyright 
16  *    notice, this list of conditions and the following disclaimer.
17  *
18  *    Redistributions in binary form must reproduce the above copyright
19  *    notice, this list of conditions and the following disclaimer in the 
20  *    documentation and/or other materials provided with the   
21  *    distribution.
22  *
23  *    Neither the name of Texas Instruments Incorporated nor the names of
24  *    its contributors may be used to endorse or promote products derived
25  *    from this software without specific prior written permission.
26  *
27  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
28  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
29  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
30  *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
31  *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
32  *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
33  *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
34  *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
35  *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
36  *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
37  *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
38  *
39  *  \par
40 */
42 /* RM Types */
43 #include <ti/drv/rm/rm_types.h>
45 /* RM external API includes */
46 #include <ti/drv/rm/rm_services.h>
48 /* RM internal API includes */
49 #include <ti/drv/rm/include/rm_servicesloc.h>
50 #include <ti/drv/rm/include/rm_loc.h>
51 #include <ti/drv/rm/include/rm_policyloc.h>
53 /* RM OSAL layer */
54 #include <rm_osal.h>
56 /**********************************************************************
57  ********************** Internal Functions ****************************
58  **********************************************************************/
60 void Rm_serviceHandler (void *rmHandle, Rm_ServiceReqInfo *serviceRequest,
61                         Rm_ServiceRespInfo *serviceResponse)
62 {
63     Rm_Inst *rmInst = (Rm_Inst *)rmHandle;
64     Rm_Transaction *transaction;
66     /* Make sure that a callback function has been provided */
67     if (serviceRequest->callback.serviceCallback == NULL)
68     {
69         /* The RM Client and Client Delegate use blocking transports to consult with a 
70          * high-level RM agent prior to providing a response to the component.  It is 
71          * assumed the component's cannot block.  Therefore, all responses must go
72          * through the callback function provided by the component.  Return an error 
73          * if the component does not provide a callback function. */
74         serviceResponse->serviceState = RM_SERVICE_ERROR_CALLBACK_NOT_PROVIDED;
75         return;
76     }
77     
78     /* Create a new transaction */
79     transaction = Rm_transactionQueueAdd(rmInst);
81     if (transaction == NULL)
82     {
83         /* Failed to create a new transaction */
84         serviceResponse->serviceState = RM_SERVICE_ERROR_TRANSACTION_FAILED_TO_ALLOCATE;
85     }
86     else
87     {
88         /* Transfer request information into the transaction */
89         transaction->type = serviceRequest->type;
90         strcpy(transaction->serviceSrcInstName, rmInst->instName);
91         transaction->callback.serviceCallback = serviceRequest->callback.serviceCallback;
92         transaction->state = RM_SERVICE_PROCESSING;
93         strcpy(&(transaction->resourceInfo.name)[0], serviceRequest->resourceName);
94         transaction->resourceInfo.base = serviceRequest->resourceBase;
95         transaction->resourceInfo.length = serviceRequest->resourceLength;
96         transaction->resourceInfo.alignment = serviceRequest->resourceAlignment;
97         strcpy(transaction->resourceInfo.nameServerName, serviceRequest->resourceNsName);
99         /* Pass the new transaction to the transaction processor */
100         Rm_transactionProcessor (rmInst, transaction);
102         /* Provide response to the component that requested the service */
103         serviceResponse->serviceState = transaction->state;
104         if (serviceResponse->serviceState == RM_SERVICE_PROCESSING)
105         {
106             /* The service is still being processed.  Provide the transaction ID
107              * back to the component so that it can sort service responses received
108              * via the provided callback function */
109             serviceResponse->serviceId = transaction->localId;
110         }
111         else if (serviceResponse->serviceState == RM_SERVICE_APPROVED_AND_COMPLETED)
112         {
113             /* Service was approved and service was an allocate request the resource
114              * data is passed back to the component */
115             if ((transaction->type == Rm_service_RESOURCE_ALLOCATE_INIT) ||
116                 (transaction->type == Rm_service_RESOURCE_ALLOCATE_USE) ||
117                 (transaction->type == Rm_service_RESOURCE_GET_BY_NAME))
118             {
119                 strcpy(serviceResponse->resourceName, transaction->resourceInfo.name);
120                 serviceResponse->resourceBase = transaction->resourceInfo.base;
121                 serviceResponse->resourceLength = transaction->resourceInfo.length;
122             }
124             /* Delete the transaction since a response was received immediately */
125             Rm_transactionQueueDelete(rmInst, transaction->localId);
126         }
127         else
128         {
129             /* The serviceState field will contain information regarding why the 
130              * service was denied or what error the service encountered.  Just delete
131              * the transaction since a response was received immediately */
132             Rm_transactionQueueDelete(rmInst, transaction->localId);
133         }
134     }
136     return;
139 /**********************************************************************
140  ********************** Application visible APIs **********************
141  **********************************************************************/
143 void Rm_servicePreMainRequest(Rm_PreMainReqCfg *reqCfg, Rm_ServiceRespInfo *preMainResp)
145     Rm_PreMainInst       *preMainInst = (Rm_PreMainInst *)reqCfg->rmPreMainHandle;
146     Rm_PolicyCheckCfg     privCheckCfg;
147     Rm_ServicePreMainReq *lastServiceReq;
149     preMainResp->serviceState = RM_SERVICE_PROCESSING;
150     preMainResp->serviceId = 0;
152     if ((reqCfg->request->type == Rm_service_RESOURCE_ALLOCATE_INIT) ||
153         (reqCfg->request->type == Rm_service_RESOURCE_ALLOCATE_USE) ||
154         (reqCfg->request->resourceBase == RM_RESOURCE_BASE_UNSPECIFIED)) {
155         /* Check request against startup policy */
156         memset((void *)&privCheckCfg, 0, sizeof(Rm_PolicyCheckCfg));
158         if (reqCfg->request->type == Rm_service_RESOURCE_ALLOCATE_INIT) {
159             privCheckCfg.type = Rm_policyCheck_INIT;
160         }
161         else {
162             privCheckCfg.type = Rm_policyCheck_USE;
163         }
164         privCheckCfg.policyDtb = preMainInst->startupDtb;
165         privCheckCfg.validInstNode = Rm_policyGetValidInstNode(preMainInst->validInstTree, 
166                                                                 preMainInst->instName);
167         privCheckCfg.resourceOffset = Rm_policyGetResourceOffset(preMainInst->startupDtb,
168                                                                   reqCfg->request->resourceName);
169         privCheckCfg.resourceBase = reqCfg->request->resourceBase;
170         privCheckCfg.resourceLength = reqCfg->request->resourceLength;
172         if (Rm_policyCheckPrivilege(&privCheckCfg, &preMainResp->serviceState)) {
173             preMainResp->serviceState = RM_SERVICE_APPROVED_AND_COMPLETED;
174         }
175         else if (preMainResp->serviceState == RM_SERVICE_PROCESSING) {
176             /* Privilege check returned FALSE without error */
177             preMainResp->serviceState = RM_SERVICE_DENIED_POLICY_DENIED_PREMAIN_ALLOCATION;
178         }
179     }
180     else {
181         preMainResp->serviceState = RM_SERVICE_DENIED_INVALID_PREMAIN_REQUEST;
182     }
184     /* Store the request for validation after post-main instance
185      * transports have been established */
186     if (preMainResp->serviceState == RM_SERVICE_APPROVED_AND_COMPLETED) {
187         /* Store the request for validation after all instances have been setup post-main */
188         lastServiceReq = preMainInst->preMainReqList;
189         while(lastServiceReq) {
190             lastServiceReq = lastServiceReq->nextPreMainReq;
191         }
192         lastServiceReq = (Rm_ServicePreMainReq *) Rm_osalMalloc (sizeof(Rm_ServicePreMainReq));
193         lastServiceReq->nextPreMainReq = NULL;
194         lastServiceReq->preMainReq = (Rm_ServiceReqInfo *) Rm_osalMalloc(sizeof(Rm_ServiceReqInfo));
195         memcpy((void *)lastServiceReq->preMainReq, (void *)reqCfg->request, sizeof(Rm_ServiceReqInfo));
197         /* Fill out response */
198         preMainResp->resourceBase = reqCfg->request->resourceBase;
199         preMainResp->resourceLength = reqCfg->request->resourceLength;
200         strcpy(preMainResp->resourceName, reqCfg->request->resourceName);
201         preMainResp->serviceId = ++preMainInst->requestCount;
202     }
205 Rm_ServicePort *Rm_serviceGetPort(Rm_Handle rmHandle)
207     Rm_ServicePort *newServicePort = NULL;
208     
209     /* Create a new service handle for the specified RM instance */
210     
211     /* Get memory for a new service port from local memory */
212     newServicePort = Rm_osalMalloc (sizeof(Rm_ServicePort));
214     /* Return NULL immediately if malloc returned NULL */
215     if (newServicePort == NULL)
216     {
217         return (newServicePort);
218     }
220     newServicePort->rmHandle = rmHandle;
221     newServicePort->rmService = Rm_serviceHandler;
223     return (newServicePort);
226 /**
227 @}
228 */