1 /*
2 * Copyright (c) 2023 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 "securec.h"
17
18 #include "devmgr_service.h"
19 #include "devhost_service_clnt.h"
20 #include "devhost_service_proxy.h"
21 #include "device_token_clnt.h"
22 #include "devmgr_service.h"
23 #include "devsvc_manager.h"
24 #include "hdf_dlist.h"
25 #include "hdf_dump_reg.h"
26 #include "hdf_io_service.h"
27 #include "hdf_log.h"
28 #include "hdf_sbuf.h"
29 #include "devmgr_dump.h"
30
31 #define HDF_LOG_TAG devmgr_dump
32
33 static const char *HELP_COMMENT =
34 " usage:\n"
35 " -help :display help information\n"
36 " -query :query all services and devices information\n"
37 " -host hostName parameter1 parameter2 ... :dump for host, maximum number of parameters is 20\n"
38 " -service serviceName parameter1 parameter2 ... :dump for device service, maximum number of parameters is 20\n";
39
40 static const uint32_t DATA_SIZE = 5000;
41 static const uint32_t LINE_SIZE = 128;
42
DevMgrDumpHostFindHost(const char * hostName,struct HdfSBuf * data,struct HdfSBuf * reply)43 static int32_t DevMgrDumpHostFindHost(const char *hostName, struct HdfSBuf *data, struct HdfSBuf *reply)
44 {
45 struct DevmgrService *devMgrSvc = (struct DevmgrService *)DevmgrServiceGetInstance();
46 if (devMgrSvc == NULL) {
47 return HDF_FAILURE;
48 }
49
50 struct DevHostServiceClnt *hostClnt = NULL;
51 int32_t ret = HDF_FAILURE;
52 bool findFlag = false;
53
54 DLIST_FOR_EACH_ENTRY(hostClnt, &devMgrSvc->hosts, struct DevHostServiceClnt, node) {
55 HDF_LOGI("%{public}s hostName:%{public}s %{public}s", __func__, hostClnt->hostName, hostName);
56 if (strcmp(hostClnt->hostName, hostName) != 0) {
57 continue;
58 }
59 findFlag = true;
60 if (hostClnt->hostService == NULL || hostClnt->hostService->Dump == NULL) {
61 (void)HdfSbufWriteString(reply, "The host does not start\n");
62 break;
63 }
64 ret = hostClnt->hostService->Dump(hostClnt->hostService, data, reply);
65 break;
66 }
67
68 if (!findFlag) {
69 (void)HdfSbufWriteString(reply, "The host does not exist\n");
70 }
71
72 return ret;
73 }
74
DevMgrDumpHost(uint32_t argv,struct HdfSBuf * data,struct HdfSBuf * reply)75 static int32_t DevMgrDumpHost(uint32_t argv, struct HdfSBuf *data, struct HdfSBuf *reply)
76 {
77 const char *hostName = HdfSbufReadString(data);
78 if (hostName == NULL) {
79 HDF_LOGE("%{public}s hostName is null", __func__);
80 return HDF_FAILURE;
81 }
82
83 struct HdfSBuf *hostData = HdfSbufTypedObtain(SBUF_IPC);
84 if (hostData == NULL) {
85 return HDF_FAILURE;
86 }
87
88 // this parameters are processed in the framework part and will not be sent to the business module
89 if (!HdfSbufWriteString(hostData, "dumpHost")) {
90 HdfSbufRecycle(hostData);
91 return HDF_FAILURE;
92 }
93
94 // the hostName will not be send to host
95 if (!HdfSbufWriteUint32(hostData, argv - 1)) {
96 HdfSbufRecycle(hostData);
97 return HDF_FAILURE;
98 }
99
100 for (uint32_t i = 0; i < argv - 1; i++) {
101 const char *value = HdfSbufReadString(data);
102 if (value == NULL || !HdfSbufWriteString(hostData, value)) {
103 HdfSbufRecycle(hostData);
104 return HDF_FAILURE;
105 }
106 }
107
108 int32_t ret = DevMgrDumpHostFindHost(hostName, hostData, reply);
109
110 HdfSbufRecycle(hostData);
111 return ret;
112 }
113
DevMgrDumpServiceFindHost(const char * servName,struct HdfSBuf * data,struct HdfSBuf * reply)114 static int32_t DevMgrDumpServiceFindHost(const char *servName, struct HdfSBuf *data, struct HdfSBuf *reply)
115 {
116 struct DevmgrService *devMgrSvc = (struct DevmgrService *)DevmgrServiceGetInstance();
117 if (devMgrSvc == NULL) {
118 return HDF_FAILURE;
119 }
120
121 struct HdfSListIterator iterator;
122 struct DevHostServiceClnt *hostClnt = NULL;
123 int32_t ret = HDF_FAILURE;
124 const char *name = NULL;
125 struct HdfSListNode *node = NULL;
126 DLIST_FOR_EACH_ENTRY(hostClnt, &devMgrSvc->hosts, struct DevHostServiceClnt, node) {
127 HdfSListIteratorInit(&iterator, &hostClnt->devices);
128 while (HdfSListIteratorHasNext(&iterator)) {
129 node = HdfSListIteratorNext(&iterator);
130 struct DeviceTokenClnt *tokenClnt = (struct DeviceTokenClnt *)node;
131 if (tokenClnt == NULL || tokenClnt->tokenIf == NULL) {
132 continue;
133 }
134 name = (tokenClnt->tokenIf->servName == NULL) ? "" : tokenClnt->tokenIf->servName;
135 HDF_LOGI("%{public}s servName:%{public}s %{public}s", __func__, name, servName);
136 if (strcmp(name, servName) != 0) {
137 continue;
138 }
139 if (hostClnt->hostService == NULL || hostClnt->hostService->Dump == NULL) {
140 return ret;
141 }
142 ret = hostClnt->hostService->Dump(hostClnt->hostService, data, reply);
143 return ret;
144 }
145 }
146
147 (void)HdfSbufWriteString(reply, "The service does not exist\n");
148 return ret;
149 }
150
DevMgrDumpService(uint32_t argv,struct HdfSBuf * data,struct HdfSBuf * reply)151 static int32_t DevMgrDumpService(uint32_t argv, struct HdfSBuf *data, struct HdfSBuf *reply)
152 {
153 const char *servName = HdfSbufReadString(data);
154 if (servName == NULL) {
155 HDF_LOGE("%{public}s serviceName is null", __func__);
156 return HDF_FAILURE;
157 }
158
159 struct HdfSBuf *servData = HdfSbufTypedObtain(SBUF_IPC);
160 if (servData == NULL) {
161 return HDF_FAILURE;
162 }
163
164 // this parameters are processed in the framework part and will not be sent to the business module
165 if (!HdfSbufWriteString(servData, "dumpService")) {
166 HdfSbufRecycle(servData);
167 return HDF_FAILURE;
168 }
169
170 // this parameters are processed in the framework part and will not be sent to the business module
171 if (!HdfSbufWriteString(servData, servName)) {
172 HdfSbufRecycle(servData);
173 return HDF_FAILURE;
174 }
175
176 if (!HdfSbufWriteUint32(servData, argv - 1)) {
177 HdfSbufRecycle(servData);
178 return HDF_FAILURE;
179 }
180
181 // the servName will not be send to business module
182 for (uint32_t i = 0; i < argv - 1; i++) {
183 const char *value = HdfSbufReadString(data);
184 if (value == NULL || !HdfSbufWriteString(servData, value)) {
185 HdfSbufRecycle(servData);
186 return HDF_FAILURE;
187 }
188 }
189
190 int32_t ret = DevMgrDumpServiceFindHost(servName, servData, reply);
191 HdfSbufRecycle(servData);
192 return ret;
193 }
194
DevMgrFillDeviceHostInfo(struct HdfSBuf * data,struct HdfSBuf * reply)195 static int32_t DevMgrFillDeviceHostInfo(struct HdfSBuf *data, struct HdfSBuf *reply)
196 {
197 const char *name = HdfSbufReadString(data);
198 if (name == NULL) {
199 return HDF_FAILURE;
200 }
201
202 char line[LINE_SIZE];
203 // The line is a combination of multiple fields, and the fields are filled with blank characters
204 (void)memset_s(line, sizeof(line), ' ', sizeof(line));
205 if (memcpy_s(line, sizeof(line), name, strlen(name)) != EOK) {
206 HDF_LOGE("%{public}s memcpy_s hostName fail", __func__);
207 return HDF_FAILURE;
208 }
209 HDF_LOGI("%{public}s devName:%{public}s", __func__, name);
210
211 uint32_t hostId;
212 (void)HdfSbufReadUint32(data, &hostId);
213 const uint32_t hostIdAlign = 32;
214 if (sprintf_s(&line[hostIdAlign], sizeof(line) - hostIdAlign, ":0x%x\n", hostId) == -1) {
215 HDF_LOGE("%{public}s sprintf_s hostId fail", __func__);
216 return HDF_FAILURE;
217 }
218
219 (void)HdfSbufWriteString(reply, line);
220 return HDF_SUCCESS;
221 }
222
DevMgrFillDeviceInfo(struct HdfSBuf * data,struct HdfSBuf * reply,uint32_t * hostCnt,uint32_t * nodeCnt)223 static void DevMgrFillDeviceInfo(struct HdfSBuf *data, struct HdfSBuf *reply, uint32_t *hostCnt, uint32_t *nodeCnt)
224 {
225 char line[LINE_SIZE];
226 const uint32_t devNameAlign = 8;
227 const uint32_t devIdAlign = 40;
228 const uint32_t servNameAlign = 56;
229 uint32_t devCnt;
230 uint32_t devId;
231 const uint32_t strEndLen = 2;
232
233 while (true) {
234 if (DevMgrFillDeviceHostInfo(data, reply) != HDF_SUCCESS) {
235 return;
236 }
237
238 (void)HdfSbufReadUint32(data, &devCnt);
239 (*hostCnt)++;
240
241 for (uint32_t i = 0; i < devCnt; i++) {
242 // The line is a combination of multiple fields, and the fields are filled with blank characters
243 (void)memset_s(line, sizeof(line), ' ', sizeof(line));
244
245 const char *name = HdfSbufReadString(data);
246 const char *devName = (name == NULL) ? "" : name;
247 if (memcpy_s(&line[devNameAlign], sizeof(line) - devNameAlign, devName, strlen(devName)) != EOK) {
248 HDF_LOGE("%{public}s memcpy_s devName fail", __func__);
249 return;
250 }
251 HDF_LOGI("%{public}s devName:%{public}s", __func__, devName);
252
253 (void)HdfSbufReadUint32(data, &devId);
254 int32_t devIdLen = sprintf_s(&line[devIdAlign], sizeof(line) - devIdAlign - 1, ":0x%x", devId);
255 if (devIdLen == -1) {
256 HDF_LOGE("%{public}s sprintf_s devId fail", __func__);
257 return;
258 }
259 line[devIdAlign + devIdLen] = ' '; // Clear the string terminator added by sprintf_s
260 line[servNameAlign - 1] = ':';
261
262 name = HdfSbufReadString(data);
263 const char *servName = (name == NULL) ? "" : name;
264 const uint32_t leftSize = sizeof(line) - servNameAlign - strEndLen;
265 if (memcpy_s(&line[servNameAlign], leftSize, servName, strlen(servName)) != EOK) {
266 HDF_LOGE("%{public}s memcpy_s servName fail %{public}s", __func__, servName);
267 return;
268 }
269 line[servNameAlign + strlen(servName)] = '\n';
270 line[servNameAlign + strlen(servName) + 1] = '\0';
271
272 (void)HdfSbufWriteString(reply, line);
273 (*nodeCnt)++;
274 }
275 }
276 return;
277 }
278
DevMgrFillServiceInfo(struct HdfSBuf * data,struct HdfSBuf * reply,uint32_t * servCnt)279 static void DevMgrFillServiceInfo(struct HdfSBuf *data, struct HdfSBuf *reply, uint32_t *servCnt)
280 {
281 char line[LINE_SIZE];
282 const uint32_t devClassAlign = 32;
283 const uint32_t devIdAlign = 48;
284 const char *servName = NULL;
285 uint32_t devClass;
286 uint32_t devId;
287
288 while (true) {
289 servName = HdfSbufReadString(data);
290 if (servName == NULL) {
291 return;
292 }
293
294 // The line is a combination of multiple fields, and the fields are filled with blank characters
295 (void)memset_s(line, sizeof(line), ' ', sizeof(line));
296 if (memcpy_s(line, sizeof(line), servName, strlen(servName)) != EOK) {
297 HDF_LOGE("%{public}s memcpy_s servName fail", __func__);
298 return;
299 }
300 HDF_LOGI("%{public}s servName:%{public}s", __func__, servName);
301
302 (void)HdfSbufReadUint32(data, &devClass);
303 int32_t devClassLen = sprintf_s(&line[devClassAlign], sizeof(line) - devClassAlign - 1, ":0x%x", devClass);
304 if (devClassLen == -1) {
305 HDF_LOGE("%{public}s sprintf_s devClass fail", __func__);
306 return;
307 }
308 line[devClassAlign + devClassLen] = ' '; // Clear the string terminator added by sprintf_s
309
310 (void)HdfSbufReadUint32(data, &devId);
311 if (sprintf_s(&line[devIdAlign], sizeof(line) - devIdAlign, ":0x%x\n", devId) == -1) {
312 HDF_LOGE("%{public}s sprintf_s devId fail", __func__);
313 return;
314 }
315
316 (void)HdfSbufWriteString(reply, line);
317 (*servCnt)++;
318 }
319
320 return;
321 }
322
DevMgrQueryUserDevice(struct HdfSBuf * reply)323 static void DevMgrQueryUserDevice(struct HdfSBuf *reply)
324 {
325 const char *title = "hdf device information in user space, format:\n" \
326 "hostName :hostId\n" \
327 " deviceName :deviceId :serviceName\n";
328
329 struct IDevmgrService *instance = DevmgrServiceGetInstance();
330 if (instance == NULL) {
331 return;
332 }
333
334 struct HdfSBuf *data = HdfSbufObtain(DATA_SIZE);
335 if (data == NULL) {
336 return;
337 }
338
339 int32_t ret = instance->ListAllDevice(instance, data);
340 if (ret != HDF_SUCCESS) {
341 HdfSbufRecycle(data);
342 return;
343 }
344
345 HdfSbufWriteString(reply, title);
346
347 uint32_t hostCnt = 0;
348 uint32_t devNodeCnt = 0;
349 DevMgrFillDeviceInfo(data, reply, &hostCnt, &devNodeCnt);
350
351 const uint32_t descLen = 128;
352 char desc[descLen];
353 (void)memset_s(desc, sizeof(desc), 0, sizeof(desc));
354 if (sprintf_s(desc, sizeof(desc), "total %u hosts, %u devNodes in user space\n\n", hostCnt, devNodeCnt) != -1) {
355 HdfSbufWriteString(reply, desc);
356 }
357
358 HdfSbufRecycle(data);
359 return;
360 }
361
DevMgrQueryUserService(struct HdfSBuf * reply)362 static void DevMgrQueryUserService(struct HdfSBuf *reply)
363 {
364 const char *title = "hdf service information in user space, format:\n" \
365 "serviceName :devClass :devId\n";
366
367 struct IDevSvcManager *instance = DevSvcManagerGetInstance();
368 if (instance == NULL) {
369 return;
370 }
371
372 struct HdfSBuf *data = HdfSbufObtain(DATA_SIZE);
373 if (data == NULL) {
374 return;
375 }
376
377 instance->ListAllService(instance, data);
378
379 HdfSbufWriteString(reply, title);
380 uint32_t servCnt = 0;
381 DevMgrFillServiceInfo(data, reply, &servCnt);
382
383 const uint32_t descLen = 128;
384 char desc[descLen];
385 (void)memset_s(desc, sizeof(desc), 0, sizeof(desc));
386 if (sprintf_s(desc, sizeof(desc), "total %u services in user space\n\n", servCnt) != -1) {
387 HdfSbufWriteString(reply, desc);
388 }
389
390 HdfSbufRecycle(data);
391 return;
392 }
393
DevMgrQueryKernelDevice(struct HdfSBuf * reply)394 static void DevMgrQueryKernelDevice(struct HdfSBuf *reply)
395 {
396 const char *title = "hdf device information in kernel space, format:\n" \
397 "hostName :hostId\n" \
398 " deviceName :deviceId :serviceName\n";
399
400 struct HdfSBuf *data = HdfSbufObtain(DATA_SIZE);
401 if (data == NULL) {
402 return;
403 }
404
405 int32_t ret = HdfListAllDevice(data);
406 if (ret != HDF_SUCCESS) {
407 HdfSbufRecycle(data);
408 return;
409 }
410
411 uint32_t hostCnt = 0;
412 uint32_t devNodeCnt = 0;
413 HdfSbufWriteString(reply, title);
414 DevMgrFillDeviceInfo(data, reply, &hostCnt, &devNodeCnt);
415
416 const uint32_t descLen = 128;
417 char desc[descLen];
418 (void)memset_s(desc, sizeof(desc), 0, sizeof(desc));
419 if (sprintf_s(desc, sizeof(desc), "total %u hosts, %u devNodes in kernel space\n\n", hostCnt, devNodeCnt) != -1) {
420 HdfSbufWriteString(reply, desc);
421 }
422
423 HdfSbufRecycle(data);
424 return;
425 }
426
DevMgrQueryKernelService(struct HdfSBuf * reply)427 static void DevMgrQueryKernelService(struct HdfSBuf *reply)
428 {
429 const char *title = "hdf service information in kernel space, format:\n" \
430 "serviceName :devClass :devId\n";
431
432 struct HdfSBuf *data = HdfSbufObtain(DATA_SIZE);
433 if (data == NULL) {
434 return;
435 }
436
437 int32_t ret = HdfListAllService(data);
438 if (ret != HDF_SUCCESS) {
439 HdfSbufRecycle(data);
440 return;
441 }
442
443 HdfSbufWriteString(reply, title);
444 uint32_t servCnt = 0;
445 DevMgrFillServiceInfo(data, reply, &servCnt);
446
447 const uint32_t descLen = 128;
448 char desc[descLen];
449 (void)memset_s(desc, sizeof(desc), 0, sizeof(desc));
450 if (sprintf_s(desc, sizeof(desc), "total %u services in kernel space\n\n", servCnt) != -1) {
451 HdfSbufWriteString(reply, desc);
452 }
453
454 HdfSbufRecycle(data);
455 return;
456 }
457
DevMgrQueryInfo(struct HdfSBuf * reply)458 static void DevMgrQueryInfo(struct HdfSBuf *reply)
459 {
460 DevMgrQueryUserDevice(reply);
461 DevMgrQueryUserService(reply);
462 DevMgrQueryKernelDevice(reply);
463 DevMgrQueryKernelService(reply);
464 return;
465 }
466
DevMgrDump(struct HdfSBuf * data,struct HdfSBuf * reply)467 static int32_t DevMgrDump(struct HdfSBuf *data, struct HdfSBuf *reply)
468 {
469 if (data == NULL || reply == NULL) {
470 return HDF_FAILURE;
471 }
472
473 uint32_t argv = 0;
474 HdfSbufReadUint32(data, &argv);
475
476 if (argv == 0) {
477 (void)HdfSbufWriteString(reply, HELP_COMMENT);
478 return HDF_SUCCESS;
479 }
480
481 const char *value = HdfSbufReadString(data);
482 if (value == NULL) {
483 HDF_LOGE("%{public}s arg is invalid", __func__);
484 return HDF_FAILURE;
485 }
486
487 HDF_LOGI("%{public}s argv:%{public}d", value, argv);
488 if (argv == 1) {
489 if (strcmp(value, "-help") == 0) {
490 (void)HdfSbufWriteString(reply, HELP_COMMENT);
491 return HDF_SUCCESS;
492 } else if (strcmp(value, "-query") == 0) {
493 DevMgrQueryInfo(reply);
494 return HDF_SUCCESS;
495 } else {
496 (void)HdfSbufWriteString(reply, HELP_COMMENT);
497 return HDF_SUCCESS;
498 }
499 } else {
500 if (strcmp(value, "-host") == 0) {
501 return DevMgrDumpHost(argv - 1, data, reply);
502 } else if (strcmp(value, "-service") == 0) {
503 return DevMgrDumpService(argv - 1, data, reply);
504 } else {
505 (void)HdfSbufWriteString(reply, HELP_COMMENT);
506 return HDF_SUCCESS;
507 }
508 }
509
510 return HDF_SUCCESS;
511 }
512
DevMgrRegisterDumpFunc(void)513 void DevMgrRegisterDumpFunc(void)
514 {
515 HdfRegisterDumpFunc(DevMgrDump);
516 }
517