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 }
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;
137 }
139 /**********************************************************************
140 ********************** Application visible APIs **********************
141 **********************************************************************/
143 void Rm_servicePreMainRequest(Rm_PreMainReqCfg *reqCfg, Rm_ServiceRespInfo *preMainResp)
144 {
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 }
203 }
205 Rm_ServicePort *Rm_serviceGetPort(Rm_Handle rmHandle)
206 {
207 Rm_ServicePort *newServicePort = NULL;
209 /* Create a new service handle for the specified RM instance */
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);
224 }
226 /**
227 @}
228 */