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