• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2022 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 <securec.h>
18 #include <stdlib.h>
19 #include <sys/syscall.h>
20 #include <unistd.h>
21 
22 #include "devhost_service_proxy.h"
23 #include "devhost_service_clnt.h"
24 #include "device_token_proxy.h"
25 #include "devmgr_query_device.h"
26 #include "devsvc_manager.h"
27 #include "hdf_cstring.h"
28 #include "hdf_core_log.h"
29 #include "hdf_sbuf.h"
30 #include "osal_mem.h"
31 #include "osal_sysevent.h"
32 
33 #include "devmgr_service_stub.h"
34 
35 #define HDF_INVALID_DEV_ID 0xffffffff
36 
37 #define HDF_LOG_TAG devmgr_service_stub
38 
DevmgrServicehostClntGetPid(struct IDevmgrService * devmgrSvc,uint16_t hostId)39 static void DevmgrServicehostClntGetPid(struct IDevmgrService *devmgrSvc, uint16_t hostId)
40 {
41     struct DevmgrService *dmService = (struct DevmgrService *)devmgrSvc;
42     if (dmService == NULL) {
43         return;
44     }
45 
46     struct DevHostServiceClnt *hostClnt = NULL;
47     DLIST_FOR_EACH_ENTRY(hostClnt, &dmService->hosts, struct DevHostServiceClnt, node) {
48         if (hostClnt->hostId == hostId) {
49             hostClnt->hostProcessId = HdfRemoteGetCallingPid();
50             break;
51         }
52     }
53 
54     return;
55 }
56 
DevmgrServiceStubDispatchAttachDeviceHost(struct IDevmgrService * devmgrSvc,struct HdfSBuf * data)57 static int32_t DevmgrServiceStubDispatchAttachDeviceHost(struct IDevmgrService *devmgrSvc, struct HdfSBuf *data)
58 {
59     uint32_t hostId = 0;
60     if (!HdfSbufReadUint32(data, &hostId)) {
61         HDF_LOGE("invalid host id");
62         return HDF_FAILURE;
63     }
64     struct HdfRemoteService *service = HdfSbufReadRemoteService(data);
65     struct IDevHostService *hostIf = DevHostServiceProxyObtain(hostId, service);
66     DevmgrServicehostClntGetPid(devmgrSvc, hostId);
67     return devmgrSvc->AttachDeviceHost(devmgrSvc, hostId, hostIf);
68 }
69 
DevmgrServiceStubDispatchAttachDevice(struct IDevmgrService * devmgrSvc,struct HdfSBuf * data)70 static int32_t DevmgrServiceStubDispatchAttachDevice(struct IDevmgrService *devmgrSvc, struct HdfSBuf *data)
71 {
72     uint32_t deviceId;
73     if (!HdfSbufReadUint32(data, &deviceId)) {
74         HDF_LOGE("%{public}s:failed to get host id and device id", __func__);
75         return HDF_ERR_INVALID_PARAM;
76     }
77     const char *servName = HdfSbufReadString(data);
78     const char *deviceName = HdfSbufReadString(data);
79     struct HdfDevTokenProxy *tokenClnt = HdfDevTokenProxyObtain(NULL);
80     if (tokenClnt == NULL) {
81         return HDF_FAILURE;
82     }
83     tokenClnt->super.devid = deviceId;
84     tokenClnt->super.servName = HdfStringCopy(servName);
85     tokenClnt->super.deviceName = HdfStringCopy(deviceName);
86     return devmgrSvc->AttachDevice(devmgrSvc, &tokenClnt->super);
87 }
88 
DevmgrServiceStubDispatchDetachDevice(struct IDevmgrService * devmgrSvc,struct HdfSBuf * data)89 static int32_t DevmgrServiceStubDispatchDetachDevice(struct IDevmgrService *devmgrSvc, struct HdfSBuf *data)
90 {
91     uint32_t deviceId;
92     if (!HdfSbufReadUint32(data, &deviceId)) {
93         HDF_LOGE("%{public}s:failed to get host id and device id", __func__);
94         return HDF_ERR_INVALID_PARAM;
95     }
96 
97     return devmgrSvc->DetachDevice(devmgrSvc, deviceId);
98 }
99 
DevmgrServiceStubDispatchLoadDevice(struct IDevmgrService * devmgrSvc,struct HdfSBuf * data)100 static int32_t DevmgrServiceStubDispatchLoadDevice(struct IDevmgrService *devmgrSvc, struct HdfSBuf *data)
101 {
102     const char *serviceName = HdfSbufReadString(data);
103     if (serviceName == NULL) {
104         HDF_LOGE("%{public}s:service name is null", __func__);
105         return HDF_ERR_INVALID_PARAM;
106     }
107     HDF_LOGI("%{public}s:load service %{public}s", __func__, serviceName);
108     return devmgrSvc->LoadDevice(devmgrSvc, serviceName);
109 }
110 
DevmgrServiceStubDispatchUnloadDevice(struct IDevmgrService * devmgrSvc,struct HdfSBuf * data)111 static int32_t DevmgrServiceStubDispatchUnloadDevice(struct IDevmgrService *devmgrSvc, struct HdfSBuf *data)
112 {
113     const char *serviceName = HdfSbufReadString(data);
114     if (serviceName == NULL) {
115         HDF_LOGE("%{public}s:service name is null", __func__);
116         return HDF_ERR_INVALID_PARAM;
117     }
118     HDF_LOGI("%{public}s:unload service %{public}s", __func__, serviceName);
119     return devmgrSvc->UnloadDevice(devmgrSvc, serviceName);
120 }
121 
DevmgrServiceStubDispatchListAllDevice(struct IDevmgrService * devmgrSvc,struct HdfSBuf * reply)122 static int32_t DevmgrServiceStubDispatchListAllDevice(struct IDevmgrService *devmgrSvc, struct HdfSBuf *reply)
123 {
124     if (reply == NULL) {
125         HDF_LOGE("%{public}s:service name is null", __func__);
126         return HDF_ERR_INVALID_PARAM;
127     }
128     HDF_LOGD("%{public}s:get all device info", __func__);
129     return devmgrSvc->ListAllDevice(devmgrSvc, reply);
130 }
131 
132 // LCOV_EXCL_START
DevmgrServiceStubListAllHost(struct IDevmgrService * devmgrSvc,struct HdfSBuf * reply)133 static int32_t DevmgrServiceStubListAllHost(struct IDevmgrService *devmgrSvc, struct HdfSBuf *reply)
134 {
135     if (reply == NULL) {
136         HDF_LOGE("%{public}s:reply is null", __func__);
137         return HDF_ERR_INVALID_PARAM;
138     }
139 
140     int32_t ret = devmgrSvc->ListAllHost(devmgrSvc, reply);
141     if (ret != HDF_SUCCESS) {
142         HDF_LOGE("%{public}s ListAllHost failed ret = %{public}d", __func__, ret);
143         return ret;
144     }
145 
146     if (!HdfSbufWriteInt32(reply, getpid())) {
147         HDF_LOGE("%{public}s: Sbuf Write devmgr pid failed", __func__);
148         return HDF_FAILURE;
149     }
150     return HDF_SUCCESS;
151 }
152 // LCOV_EXCL_STOP
153 
DevmgrServiceStubDispatch(struct HdfRemoteService * stub,int code,struct HdfSBuf * data,struct HdfSBuf * reply)154 int32_t DevmgrServiceStubDispatch(struct HdfRemoteService *stub, int code, struct HdfSBuf *data, struct HdfSBuf *reply)
155 {
156     int32_t ret = HDF_FAILURE;
157     struct DevmgrServiceStub *serviceStub = (struct DevmgrServiceStub *)stub;
158     if (serviceStub == NULL) {
159         return HDF_ERR_INVALID_PARAM;
160     }
161     struct IDevmgrService *super = (struct IDevmgrService *)&serviceStub->super;
162     if (!HdfRemoteServiceCheckInterfaceToken(serviceStub->remote, data)) {
163         HDF_LOGE("%{public}s: invalid interface token, code=%{public}d", __func__, code);
164         return HDF_ERR_INVALID_PARAM;
165     }
166     HDF_LOGD("DevmgrServiceStubDispatch called: code=%{public}d, calling pid=%{public}d",
167         code, HdfRemoteGetCallingPid());
168     switch (code) {
169         case DEVMGR_SERVICE_ATTACH_DEVICE_HOST:
170             ret = DevmgrServiceStubDispatchAttachDeviceHost(super, data);
171             break;
172         case DEVMGR_SERVICE_ATTACH_DEVICE:
173             ret = DevmgrServiceStubDispatchAttachDevice(super, data);
174             break;
175         case DEVMGR_SERVICE_DETACH_DEVICE:
176             ret = DevmgrServiceStubDispatchDetachDevice(super, data);
177             break;
178         case DEVMGR_SERVICE_LOAD_DEVICE:
179             ret = DevmgrServiceStubDispatchLoadDevice(super, data);
180             break;
181         case DEVMGR_SERVICE_UNLOAD_DEVICE:
182             ret = DevmgrServiceStubDispatchUnloadDevice(super, data);
183             break;
184         case DEVMGR_SERVICE_QUERY_DEVICE:
185             ret = DevFillQueryDeviceInfo(super, data, reply);
186             break;
187         case DEVMGR_SERVICE_LIST_ALL_DEVICE:
188             ret = DevmgrServiceStubDispatchListAllDevice(super, reply);
189             break;
190         case DEVMGR_SERVICE_LIST_ALL_HOST:
191             ret = DevmgrServiceStubListAllHost(super, reply);
192             break;
193         default:
194             return HdfRemoteServiceDefaultDispatch(serviceStub->remote, code, data, reply);
195     }
196     if (ret != HDF_SUCCESS) {
197         HDF_LOGE("%{public}s devmgr service stub dispach failed, cmd id is %{public}d, ret = %{public}d", __func__,
198             code, ret);
199     }
200     return ret;
201 }
202 
203 // LCOV_EXCL_START
RemoveModule(const char * module)204 static void RemoveModule(const char *module)
205 {
206     uint32_t flags = O_NONBLOCK | O_EXCL;
207     if (syscall(__NR_delete_module, module, flags) != 0) {
208         HDF_LOGE("failed to remove module %{public}s", module);
209     }
210 }
211 
InstallModule(const char * module)212 static int32_t InstallModule(const char *module)
213 {
214     HDF_LOGI("try to install module %{public}s", module);
215 
216     int fd = open(module, O_RDONLY | O_CLOEXEC);
217     if (fd < 0) {
218         HDF_LOGE("module %{public}s is invalid", module);
219         return HDF_ERR_BAD_FD;
220     }
221     int32_t ret = (int32_t)syscall(SYS_finit_module, fd, "", 0);
222     if (ret != 0) {
223         HDF_LOGE("failed to install module %{public}s, %{public}d", module, ret);
224     }
225 
226     close(fd);
227     fd = -1;
228     return ret;
229 }
230 
MakeModulePath(char * buffer,const char * moduleName)231 static int32_t MakeModulePath(char *buffer, const char *moduleName)
232 {
233     char temp[PATH_MAX] = {0};
234     if (sprintf_s(temp, PATH_MAX, "%s/%s.ko", HDF_MODULE_DIR, moduleName) <= 0) {
235         HDF_LOGI("driver module path sprintf failed: %{public}s", moduleName);
236         return HDF_FAILURE;
237     }
238     HDF_LOGI("driver module file: %{public}s", temp);
239 
240     char *path = realpath(temp, buffer);
241     if (path == NULL || strncmp(path, HDF_MODULE_DIR, strlen(HDF_MODULE_DIR)) != 0) {
242         HDF_LOGE("driver module file is invalid: %{public}s", temp);
243         return HDF_ERR_INVALID_PARAM;
244     }
245 
246     return HDF_SUCCESS;
247 }
248 
ModuleSysEventHandle(struct HdfSysEventNotifyNode * self,uint64_t eventClass,uint32_t event,const char * content)249 static int32_t ModuleSysEventHandle(
250     struct HdfSysEventNotifyNode *self, uint64_t eventClass, uint32_t event, const char *content)
251 {
252     if (self == NULL || (eventClass & HDF_SYSEVENT_CLASS_MODULE) == 0 || content == NULL) {
253         return HDF_ERR_INVALID_PARAM;
254     }
255 
256     (void)self;
257     HDF_LOGI("handle driver module: %{public}s", content);
258     char modulePath[PATH_MAX] = {0};
259     int32_t ret = MakeModulePath(modulePath, content);
260     if (ret != HDF_SUCCESS) {
261         return ret;
262     }
263     switch (event) {
264         case KEVENT_MODULE_INSTALL:
265             ret = InstallModule(modulePath);
266             break;
267         case KEVENT_MODULE_REMOVE:
268             RemoveModule(modulePath);
269             break;
270         default:
271             ret = HDF_ERR_NOT_SUPPORT;
272             break;
273     }
274 
275     return ret;
276 }
277 // LCOV_EXCL_STOP
278 
DriverModuleLoadHelperInit(void)279 static int32_t DriverModuleLoadHelperInit(void)
280 {
281     static struct HdfSysEventNotifyNode sysEventNotify = {
282         .callback = ModuleSysEventHandle,
283     };
284 
285     int32_t ret = HdfSysEventNotifyRegister(&sysEventNotify, HDF_SYSEVENT_CLASS_MODULE);
286     if (ret != HDF_SUCCESS) {
287         HDF_LOGW("ModuleLoadHelper:failed to register module event listener");
288     }
289 
290     return ret;
291 }
292 
293 static struct HdfRemoteDispatcher g_devmgrDispatcher = {
294     .Dispatch = DevmgrServiceStubDispatch,
295 };
296 
DevmgrServiceStubStartService(struct IDevmgrService * inst)297 int DevmgrServiceStubStartService(struct IDevmgrService *inst)
298 {
299     struct DevmgrServiceStub *fullService = (struct DevmgrServiceStub *)inst;
300     if (fullService == NULL) {
301         HDF_LOGE("Start service failed, fullService is null");
302         return HDF_ERR_INVALID_PARAM;
303     }
304 
305     struct IDevSvcManager *serviceManager = DevSvcManagerGetInstance();
306     struct HdfRemoteService *remoteService = HdfRemoteServiceObtain((struct HdfObject *)inst, &g_devmgrDispatcher);
307     if (serviceManager == NULL || remoteService == NULL) {
308         HDF_LOGE("Start service failed, get service manager failed or remoteService obtain err");
309         return HDF_FAILURE;
310     }
311 
312     if (!HdfRemoteServiceSetInterfaceDesc(remoteService, "HDI.IDeviceManager.V1_0")) {
313         HDF_LOGE("%{public}s: failed to init interface desc", __func__);
314         HdfRemoteServiceRecycle(remoteService);
315         return HDF_FAILURE;
316     }
317     struct HdfDeviceObject *deviceObject = OsalMemCalloc(sizeof(struct HdfDeviceObject));
318     if (deviceObject == NULL) {
319         HDF_LOGE("%{public}s: failed to malloc device obj", __func__);
320         HdfRemoteServiceRecycle(remoteService);
321         return HDF_ERR_MALLOC_FAIL;
322     }
323     deviceObject->service = (struct IDeviceIoService *)remoteService;
324     struct HdfServiceInfo info;
325     info.devId = HDF_INVALID_DEV_ID;
326     info.servName = DEVICE_MANAGER_SERVICE;
327     info.servInfo = NULL;
328     info.devClass = DEVICE_CLASS_DEFAULT;
329     int status = DevSvcManagerAddService(serviceManager, deviceObject, &info);
330     if (status != HDF_SUCCESS) {
331         HDF_LOGE("%{public}s: failed to add service", __func__);
332         HdfRemoteServiceRecycle(remoteService);
333         OsalMemFree(deviceObject);
334         return status;
335     }
336     fullService->remote = remoteService;
337 
338     (void)DriverModuleLoadHelperInit();
339     status = DevmgrServiceStartService((struct IDevmgrService *)&fullService->super);
340     if (status != HDF_SUCCESS) {
341         HDF_LOGE("%{public}s: failed to start service", __func__);
342         HdfRemoteServiceRecycle(remoteService);
343         OsalMemFree(deviceObject);
344         return status;
345     }
346     return DevSvcManagerStartService();
347 }
348 
DevmgrServiceStubConstruct(struct DevmgrServiceStub * inst)349 static void DevmgrServiceStubConstruct(struct DevmgrServiceStub *inst)
350 {
351     struct IDevmgrService *pvtbl = (struct IDevmgrService *)inst;
352 
353     DevmgrServiceFullConstruct(&inst->super);
354     pvtbl->StartService = DevmgrServiceStubStartService;
355     inst->remote = NULL;
356     OsalMutexInit(&inst->devmgrStubMutx);
357 }
358 
DevmgrServiceStubCreate(void)359 struct HdfObject *DevmgrServiceStubCreate(void)
360 {
361     static struct DevmgrServiceStub *instance = NULL;
362     if (instance == NULL) {
363         instance = (struct DevmgrServiceStub *)OsalMemCalloc(sizeof(struct DevmgrServiceStub));
364         if (instance == NULL) {
365             HDF_LOGE("Creating devmgr service stub failed, alloc mem error");
366             return NULL;
367         }
368         DevmgrServiceStubConstruct(instance);
369     }
370     return (struct HdfObject *)instance;
371 }
372 
DevmgrServiceStubRelease(struct HdfObject * object)373 void DevmgrServiceStubRelease(struct HdfObject *object)
374 {
375     struct DevmgrServiceStub *instance = (struct DevmgrServiceStub *)object;
376     if (instance != NULL) {
377         if (instance->remote != NULL) {
378             HdfRemoteServiceRecycle(instance->remote);
379             instance->remote = NULL;
380         }
381         OsalMutexDestroy(&instance->devmgrStubMutx);
382         OsalMemFree(instance);
383     }
384 }
385