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