• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include <fcntl.h>
17 #include <limits.h>
18 #include <securec.h>
19 #include <stdlib.h>
20 #include <sys/syscall.h>
21 #include <unistd.h>
22 
23 #include "devhost_service_proxy.h"
24 #include "device_token_proxy.h"
25 #include "devmgr_query_device.h"
26 #include "devsvc_manager.h"
27 #include "hdf_log.h"
28 #include "hdf_sbuf.h"
29 #include "osal_mem.h"
30 #include "osal_sysevent.h"
31 
32 #include "devmgr_service_stub.h"
33 
34 #define HDF_LOG_TAG devmgr_service_stub
35 
DevmgrServiceStubDispatchAttachDevice(struct IDevmgrService * devmgrSvc,struct HdfSBuf * data)36 static int32_t DevmgrServiceStubDispatchAttachDevice(struct IDevmgrService *devmgrSvc, struct HdfSBuf *data)
37 {
38     uint32_t deviceId;
39     if (!HdfSbufReadUint32(data, &deviceId)) {
40         HDF_LOGE("%{public}s:failed to get host id and device id", __func__);
41         return HDF_ERR_INVALID_PARAM;
42     }
43 
44     struct HdfDevTokenProxy *tokenClnt = HdfDevTokenProxyObtain(NULL);
45     if (tokenClnt == NULL) {
46         return HDF_FAILURE;
47     }
48     tokenClnt->super.devid = deviceId;
49     return devmgrSvc->AttachDevice(devmgrSvc, &tokenClnt->super);
50 }
51 
DevmgrServiceStubDispatchDetachDevice(struct IDevmgrService * devmgrSvc,struct HdfSBuf * data)52 static int32_t DevmgrServiceStubDispatchDetachDevice(struct IDevmgrService *devmgrSvc, struct HdfSBuf *data)
53 {
54     uint32_t deviceId;
55     if (!HdfSbufReadUint32(data, &deviceId)) {
56         HDF_LOGE("%{public}s:failed to get host id and device id", __func__);
57         return HDF_ERR_INVALID_PARAM;
58     }
59 
60     return devmgrSvc->DetachDevice(devmgrSvc, deviceId);
61 }
62 
DevmgrServiceStubDispatchLoadDevice(struct IDevmgrService * devmgrSvc,struct HdfSBuf * data)63 static int32_t DevmgrServiceStubDispatchLoadDevice(struct IDevmgrService *devmgrSvc, struct HdfSBuf *data)
64 {
65     const char *serviceName = HdfSbufReadString(data);
66     if (serviceName == NULL) {
67         HDF_LOGE("%{public}s:service name is null", __func__);
68         return HDF_ERR_INVALID_PARAM;
69     }
70     HDF_LOGI("%{public}s:load service %{public}s", __func__, serviceName);
71     return devmgrSvc->LoadDevice(devmgrSvc, serviceName);
72 }
73 
DevmgrServiceStubDispatchUnloadDevice(struct IDevmgrService * devmgrSvc,struct HdfSBuf * data)74 static int32_t DevmgrServiceStubDispatchUnloadDevice(struct IDevmgrService *devmgrSvc, struct HdfSBuf *data)
75 {
76     const char *serviceName = HdfSbufReadString(data);
77     if (serviceName == NULL) {
78         HDF_LOGE("%{public}s:service name is null", __func__);
79         return HDF_ERR_INVALID_PARAM;
80     }
81     HDF_LOGI("%{public}s:unload service %{public}s", __func__, serviceName);
82     return devmgrSvc->UnloadDevice(devmgrSvc, serviceName);
83 }
84 
DevmgrServiceStubDispatch(struct HdfRemoteService * stub,int code,struct HdfSBuf * data,struct HdfSBuf * reply)85 int32_t DevmgrServiceStubDispatch(struct HdfRemoteService *stub, int code, struct HdfSBuf *data, struct HdfSBuf *reply)
86 {
87     int32_t ret = HDF_FAILURE;
88     struct DevmgrServiceStub *serviceStub = (struct DevmgrServiceStub *)stub;
89     if (serviceStub == NULL) {
90         return HDF_ERR_INVALID_PARAM;
91     }
92     struct IDevmgrService *super = (struct IDevmgrService *)&serviceStub->super;
93     if (!HdfRemoteServiceCheckInterfaceToken(serviceStub->remote, data)) {
94         HDF_LOGE("%{public}s: invalid interface token, code=%{public}d", __func__, code);
95         return HDF_ERR_INVALID_PARAM;
96     }
97     uint32_t hostId = 0;
98     switch (code) {
99         case DEVMGR_SERVICE_ATTACH_DEVICE_HOST:
100             if (!HdfSbufReadUint32(data, &hostId)) {
101                 HDF_LOGE("invalid host id");
102                 return HDF_FAILURE;
103             }
104             struct HdfRemoteService *service = HdfSbufReadRemoteService(data);
105             struct IDevHostService *hostIf = DevHostServiceProxyObtain(hostId, service);
106             ret = super->AttachDeviceHost(super, hostId, hostIf);
107             break;
108         case DEVMGR_SERVICE_ATTACH_DEVICE:
109             ret = DevmgrServiceStubDispatchAttachDevice(super, data);
110             break;
111         case DEVMGR_SERVICE_DETACH_DEVICE:
112             ret = DevmgrServiceStubDispatchDetachDevice(super, data);
113             break;
114         case DEVMGR_SERVICE_LOAD_DEVICE:
115             ret = DevmgrServiceStubDispatchLoadDevice(super, data);
116             break;
117         case DEVMGR_SERVICE_UNLOAD_DEVICE:
118             ret = DevmgrServiceStubDispatchUnloadDevice(super, data);
119             break;
120         case DEVMGR_SERVICE_QUERY_DEVICE:
121             ret = DevFillQueryDeviceInfo(super, data, reply);
122             break;
123         default:
124             break;
125     }
126     if (ret != HDF_SUCCESS) {
127         HDF_LOGE("%{public}s devmgr service stub dispach failed, cmd id is %{public}d, ret = %{public}d", __func__,
128             code, ret);
129         HdfSbufWriteInt32(reply, ret);
130     }
131 
132     return ret;
133 }
134 
RemoveModule(const char * module)135 static void RemoveModule(const char *module)
136 {
137     uint32_t flags = O_NONBLOCK | O_EXCL;
138     if (syscall(__NR_delete_module, module, flags) != 0) {
139         HDF_LOGE("failed to remove module %{public}s", module);
140     }
141 }
142 
InstallModule(const char * module)143 static int32_t InstallModule(const char *module)
144 {
145     HDF_LOGI("try to install module %{public}s", module);
146 
147     int fd = open(module, O_RDONLY | O_CLOEXEC);
148     if (fd < 0) {
149         HDF_LOGE("module %{public}s is invalid", module);
150         return HDF_ERR_BAD_FD;
151     }
152     int32_t ret = syscall(SYS_finit_module, fd, "", 0);
153     if (ret != 0) {
154         HDF_LOGE("failed to install module %{public}s", module);
155     }
156 
157     close(fd);
158     return ret;
159 }
160 
MakeModulePath(char * buffer,const char * moduleName)161 static int32_t MakeModulePath(char *buffer, const char *moduleName)
162 {
163     char temp[PATH_MAX] = {0};
164     if (sprintf_s(temp, PATH_MAX, "%s/%s.ko", HDF_MODULE_DIR, moduleName) <= 0) {
165         HDF_LOGI("driver module path sprintf failed: %{public}s", moduleName);
166         return HDF_FAILURE;
167     }
168     HDF_LOGI("driver module file: %{public}s", temp);
169 
170     char *path = realpath(temp, buffer);
171     if (path == NULL || strncmp(path, HDF_MODULE_DIR, strlen(HDF_MODULE_DIR)) != 0) {
172         HDF_LOGE("driver module file is invalud: %{public}s", temp);
173         return HDF_ERR_INVALID_PARAM;
174     }
175 
176     return HDF_SUCCESS;
177 }
178 
ModuleSysEventHandle(struct HdfSysEventNotifyNode * self,uint64_t eventClass,uint32_t event,const char * content)179 static int32_t ModuleSysEventHandle(
180     struct HdfSysEventNotifyNode *self, uint64_t eventClass, uint32_t event, const char *content)
181 {
182     if (self == NULL || (eventClass & HDF_SYSEVENT_CLASS_MODULE) == 0 || content == NULL) {
183         return HDF_ERR_INVALID_PARAM;
184     }
185 
186     HDF_LOGI("handle driver module: %{public}s", content);
187     char modulePath[PATH_MAX] = {0};
188     int32_t ret = MakeModulePath(modulePath, content);
189     if (ret != HDF_SUCCESS) {
190         return ret;
191     }
192     switch (event) {
193         case KEVENT_MODULE_INSTALL:
194             ret = InstallModule(modulePath);
195             break;
196         case KEVENT_MODULE_REMOVE:
197             RemoveModule(modulePath);
198             break;
199         default:
200             ret = HDF_ERR_NOT_SUPPORT;
201             break;
202     }
203 
204     return ret;
205 }
206 
DriverModuleLoadHelperInit(void)207 static int32_t DriverModuleLoadHelperInit(void)
208 {
209     static struct HdfSysEventNotifyNode sysEventNotify = {
210         .callback = ModuleSysEventHandle,
211     };
212 
213     int32_t ret = HdfSysEventNotifyRegister(&sysEventNotify, HDF_SYSEVENT_CLASS_MODULE);
214     if (ret != HDF_SUCCESS) {
215         HDF_LOGW("ModuleLoadHelper:failed to register module event listener");
216     }
217 
218     return ret;
219 }
220 
221 static struct HdfRemoteDispatcher g_devmgrDispatcher = {
222     .Dispatch = DevmgrServiceStubDispatch,
223 };
224 
DevmgrServiceStubStartService(struct IDevmgrService * inst)225 int DevmgrServiceStubStartService(struct IDevmgrService *inst)
226 {
227     struct DevmgrServiceStub *fullService = (struct DevmgrServiceStub *)inst;
228     if (fullService == NULL) {
229         return HDF_ERR_INVALID_PARAM;
230     }
231 
232     struct IDevSvcManager *serviceManager = DevSvcManagerGetInstance();
233     if (serviceManager == NULL) {
234         HDF_LOGI("Start service failed, fullService is null");
235         return HDF_ERR_INVALID_OBJECT;
236     }
237 
238     int status = DevSvcManagerStartService();
239     if (status != HDF_SUCCESS) {
240         return status;
241     }
242 
243     struct HdfRemoteService *remoteService = HdfRemoteServiceObtain((struct HdfObject *)inst, &g_devmgrDispatcher);
244     if (remoteService == NULL) {
245         HDF_LOGI("failed to start devmgr, remoteService obtain err");
246         return HDF_ERR_MALLOC_FAIL;
247     }
248     if (!HdfRemoteServiceSetInterfaceDesc(remoteService, "HDI.IDeviceManager.V1_0")) {
249         HDF_LOGE("%{public}s: failed to init interface desc", __func__);
250         HdfRemoteServiceRecycle(remoteService);
251         return HDF_FAILURE;
252     }
253     struct HdfDeviceObject *deviceObject = OsalMemCalloc(sizeof(struct HdfDeviceObject));
254     if (deviceObject == NULL) {
255         HdfRemoteServiceRecycle(remoteService);
256         return HDF_ERR_MALLOC_FAIL;
257     }
258     deviceObject->service = (struct IDeviceIoService *)remoteService;
259     status = DevSvcManagerAddService(serviceManager, DEVICE_MANAGER_SERVICE, DEVICE_CLASS_DEFAULT, deviceObject, NULL);
260     if (status != HDF_SUCCESS) {
261         HdfRemoteServiceRecycle(remoteService);
262         OsalMemFree(deviceObject);
263         return status;
264     }
265     fullService->remote = remoteService;
266 
267     DriverModuleLoadHelperInit();
268 
269     return DevmgrServiceStartService((struct IDevmgrService *)&fullService->super);
270 }
271 
DevmgrServiceStubConstruct(struct DevmgrServiceStub * inst)272 static void DevmgrServiceStubConstruct(struct DevmgrServiceStub *inst)
273 {
274     struct IDevmgrService *pvtbl = (struct IDevmgrService *)inst;
275 
276     DevmgrServiceFullConstruct(&inst->super);
277     pvtbl->StartService = DevmgrServiceStubStartService;
278     inst->remote = NULL;
279     OsalMutexInit(&inst->devmgrStubMutx);
280 }
281 
DevmgrServiceStubCreate(void)282 struct HdfObject *DevmgrServiceStubCreate(void)
283 {
284     static struct DevmgrServiceStub *instance = NULL;
285     if (instance == NULL) {
286         instance = (struct DevmgrServiceStub *)OsalMemCalloc(sizeof(struct DevmgrServiceStub));
287         if (instance == NULL) {
288             HDF_LOGE("Creating devmgr service stub failed, alloc mem error");
289             return NULL;
290         }
291         DevmgrServiceStubConstruct(instance);
292     }
293     return (struct HdfObject *)instance;
294 }
295 
DevmgrServiceStubRelease(struct HdfObject * object)296 void DevmgrServiceStubRelease(struct HdfObject *object)
297 {
298     struct DevmgrServiceStub *instance = (struct DevmgrServiceStub *)object;
299     if (instance != NULL) {
300         if (instance->remote != NULL) {
301             HdfRemoteServiceRecycle(instance->remote);
302             instance->remote = NULL;
303         }
304         OsalMutexDestroy(&instance->devmgrStubMutx);
305         OsalMemFree(instance);
306     }
307 }
308