Line data Source code
1 : /**
2 : * Copyright (c) 2026 Huawei Technologies Co., Ltd.
3 : * This program is free software, you can redistribute it and/or modify it under the terms and conditions of
4 : * CANN Open Software License Agreement Version 2.0 (the "License").
5 : * Please refer to the License for details. You may not use this file except in compliance with the License.
6 : * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
7 : * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
8 : * See LICENSE in the root of the software repository for the full text of the License.
9 : */
10 : #include "hal.h"
11 : #include <stdint.h>
12 : #include <stdio.h>
13 : #include <time.h>
14 : #include <dlfcn.h>
15 : #include <stdarg.h>
16 : #include <stdlib.h>
17 : #include <string.h>
18 : #include <ctype.h>
19 : #include <string.h>
20 : #include <unistd.h>
21 : #include <sys/socket.h>
22 : #include <sys/ioctl.h>
23 : #include <net/if.h>
24 : #include <net/if_arp.h>
25 : #include <errno.h>
26 : #include <pthread.h>
27 : #include <syslog.h>
28 : #include "securec.h"
29 :
30 : #define MAX_LINE_LENGTH 256 // 每行最大长度
31 : #define TARGET_KEY "Driver_Install_Path_Param" // 要查找的key
32 :
33 : #define DRIVER_DRFAULT_INSTALL_PATH "/usr/local/Ascend"
34 : #define DRIVER_TOPO_FILE_DIR_PATH "driver/topo/950"
35 : #define MAX_TOPO_FILENAME_LEN (64)
36 :
37 : #define HAL_TRUE (1)
38 : #define HAL_FALSE (0)
39 :
40 : #define MODULE_TYPE_SYSTEM (0)
41 : #define INFO_TYPE_SERVER_ID (27)
42 : #define INFO_TYPE_SPOD_ID (29)
43 : #define INFO_TYPE_MAINBOARD_ID (39)
44 : #define INFO_TYPE_CHASSI_ID (48)
45 : #define INFO_TYPE_SPOD_TYPE (49)
46 :
47 : enum dcmi_main_cmd {
48 : DCMI_MAIN_CMD_DVPP = 0,
49 : DCMI_MAIN_CMD_ISP,
50 : DCMI_MAIN_CMD_TS_GROUP_NUM,
51 : DCMI_MAIN_CMD_CAN,
52 : DCMI_MAIN_CMD_UART,
53 : DCMI_MAIN_CMD_UPGRADE = 5,
54 : DCMI_MAIN_CMD_UFS,
55 : DCMI_MAIN_CMD_OS_POWER,
56 : DCMI_MAIN_CMD_LP,
57 : DCMI_MAIN_CMD_MEMORY,
58 : DCMI_MAIN_CMD_RECOVERY,
59 : DCMI_MAIN_CMD_TS,
60 : DCMI_MAIN_CMD_CHIP_INF,
61 : DCMI_MAIN_CMD_QOS,
62 : DCMI_MAIN_CMD_SOC_INFO,
63 : DCMI_MAIN_CMD_HCCS = 16,
64 : DCMI_MAIN_CMD_TEMP = 50,
65 : DCMI_MAIN_CMD_SVM = 51,
66 : DCMI_MAIN_CMD_VDEV_MNG,
67 : DCMI_MAIN_CMD_SIO = 56,
68 : DCMI_MAIN_CMD_DEVICE_SHARE = 0x8001,
69 : DCMI_MAIN_CMD_MAX
70 : };
71 :
72 : typedef enum {
73 : DCMI_CHIP_INFO_SUB_CMD_CHIP_ID,
74 : DCMI_CHIP_INFO_SUB_CMD_SPOD_INFO,
75 : DCMI_CHIP_INFO_SUB_CMD_MAX = 0xFF,
76 : }DCMI_CHIP_INFO_SUB_CMD;
77 :
78 :
79 :
80 : static int (*dcmi_init)(void);
81 :
82 : static int (*dcmiv2_get_urma_device_cnt)(int npu_id, unsigned int *dev_cnt);
83 :
84 : static int (*dcmiv2_get_eid_list_by_urma_dev_index)(int npu_id,
85 : int urma_dev_index,
86 : dcmi_urma_eid_info_t* eid_list,
87 : int* eid_cnt);
88 :
89 : static int (*dcmiv2_get_device_pcie_info)(int npu_id, struct dcmi_pcie_info_all* pcie_info);
90 :
91 : static int (*aclrtGetUserDevIdByPhyDevId)(const int32_t phyId, int32_t *const userDevId);
92 :
93 : static int (*aclrtGetLogicDevIdByUserDevId)(const int32_t userDevId, int32_t *const logicId);
94 :
95 : static int (*halGetDeviceInfo)(unsigned int devId, uint32_t moduleType, int32_t infoType, int64_t *value);
96 :
97 2 : void* hal_dlopen(const char *filename, int flag)
98 : {
99 2 : return dlopen(filename, flag);
100 : }
101 :
102 0 : void* hal_dlsym(void *handle, const char *symbol)
103 : {
104 0 : return dlsym(handle, symbol);
105 : }
106 :
107 19 : int load_dcmi()
108 : {
109 : static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
110 : static void* dcmi = NULL;
111 : static void* acl = NULL;
112 : static int isInit = HAL_FALSE;
113 19 : pthread_mutex_lock(&mutex);
114 19 : if (dcmi != NULL && acl != NULL && isInit == HAL_TRUE) {
115 17 : pthread_mutex_unlock(&mutex);
116 17 : return 0;
117 : }
118 2 : if(dcmi == NULL || acl == NULL) {
119 2 : dcmi = hal_dlopen("libdcmi.so", RTLD_LAZY);
120 2 : acl = hal_dlopen("libacl_rt.so", RTLD_LAZY);
121 : }
122 :
123 2 : if(dcmi == NULL || acl == NULL) {
124 1 : pthread_mutex_unlock(&mutex);
125 1 : return -1;
126 : }
127 1 : dcmi_init = hal_dlsym(dcmi, "dcmiv2_init");
128 1 : dcmiv2_get_urma_device_cnt = hal_dlsym(dcmi, "dcmiv2_get_urma_device_cnt");
129 1 : dcmiv2_get_eid_list_by_urma_dev_index = hal_dlsym(dcmi, "dcmiv2_get_eid_list_by_urma_dev_index");
130 1 : dcmiv2_get_device_pcie_info = hal_dlsym(dcmi, "dcmiv2_get_device_pcie_info");
131 :
132 : //兼容性处理 aclrtGetLogicDevIdByPhyDevId接口语义错误,实际返回的是UserDevId,优先使用新接口
133 1 : aclrtGetUserDevIdByPhyDevId = hal_dlsym(acl, "aclrtGetUserDevIdByPhyDevId");
134 1 : if (aclrtGetUserDevIdByPhyDevId == NULL) {
135 0 : aclrtGetUserDevIdByPhyDevId = hal_dlsym(acl, "aclrtGetLogicDevIdByPhyDevId");
136 : }
137 :
138 1 : halGetDeviceInfo = hal_dlsym(acl, "halGetDeviceInfo");
139 1 : aclrtGetLogicDevIdByUserDevId = hal_dlsym(acl, "aclrtGetLogicDevIdByUserDevId");
140 :
141 1 : if ((dcmi_init == NULL) || (dcmiv2_get_urma_device_cnt == NULL)
142 1 : || (dcmiv2_get_eid_list_by_urma_dev_index == NULL) || (halGetDeviceInfo == NULL)
143 1 : || (dcmiv2_get_device_pcie_info ==NULL) || (aclrtGetUserDevIdByPhyDevId == NULL)
144 1 : || (aclrtGetLogicDevIdByUserDevId == NULL)) {
145 0 : pthread_mutex_unlock(&mutex);
146 0 : return -1;
147 : }
148 1 : (void)dcmi_init(); // dcmi_init可能已经调用过了
149 1 : isInit = HAL_TRUE;
150 1 : pthread_mutex_unlock(&mutex);
151 1 : return 0;
152 : }
153 :
154 19 : int hal_get_mainboard_id(int phyId, unsigned int* mainboardId)
155 : {
156 19 : unsigned int logicId = 0;
157 19 : if (hal_get_logicid_from_phyid((unsigned int)phyId, &logicId) != 0) {
158 1 : return -1;
159 : }
160 18 : int64_t value = 0;
161 18 : int ret = halGetDeviceInfo(logicId, MODULE_TYPE_SYSTEM, INFO_TYPE_MAINBOARD_ID, &value);
162 18 : if (ret == 0) {
163 18 : *mainboardId = (unsigned int)value;
164 : }
165 18 : return ret;
166 : }
167 :
168 : #define MAX_IFREQ_NUM (16)
169 101 : int get_server_id(char* server_id, size_t len) {
170 : int sock_fd;
171 : struct ifconf ifc;
172 : struct ifreq ifr[MAX_IFREQ_NUM];
173 : int if_count, i;
174 :
175 101 : if ((sock_fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
176 0 : return -1;
177 : }
178 :
179 101 : ifc.ifc_len = sizeof(ifr);
180 101 : ifc.ifc_buf = (char*)ifr;
181 101 : if (ioctl(sock_fd, SIOCGIFCONF, &ifc) < 0) {
182 0 : close(sock_fd);
183 0 : return -1;
184 : }
185 :
186 101 : if_count = ifc.ifc_len / sizeof(struct ifreq);
187 202 : for (i = 0; i < if_count; ++i) {
188 202 : if (strcmp(ifr[i].ifr_name, "lo") == 0) {
189 101 : continue;
190 : }
191 101 : if (ioctl(sock_fd, SIOCGIFHWADDR, &ifr[i]) < 0) {
192 0 : continue;
193 : }
194 101 : if (ifr[i].ifr_hwaddr.sa_family != ARPHRD_ETHER) {
195 0 : continue;
196 : }
197 101 : unsigned char *mac = (unsigned char*)ifr[i].ifr_hwaddr.sa_data;
198 101 : sprintf_s(server_id, len, "%02X%02X%02X%02X%02X%02X",
199 101 : mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
200 101 : close(sock_fd);
201 101 : return 0;
202 : }
203 0 : close(sock_fd);
204 0 : return -1;
205 : }
206 :
207 0 : int hal_get_eid_list_by_phy_id(int phyId, dcmi_urma_eid_info_t* eidList, size_t* eidCnt)
208 : {
209 0 : unsigned int logicId = 0;
210 0 : if (hal_get_logicid_from_phyid((unsigned int)phyId, &logicId) != 0) {
211 0 : return -1;
212 : }
213 0 : unsigned int dev_cnt = 0;
214 0 : int ret = dcmiv2_get_urma_device_cnt((int)logicId, &dev_cnt);
215 0 : if (ret != 0) {
216 0 : return ret;
217 : }
218 0 : size_t eid_current_cnt = 0;
219 0 : size_t eid_space_left = (*eidCnt);
220 0 : for (size_t i = 0; i < dev_cnt; ++i) {
221 0 : int left = (int)eid_space_left;
222 0 : ret = dcmiv2_get_eid_list_by_urma_dev_index((int)logicId, i, &eidList[eid_current_cnt], &left);
223 0 : if (ret != 0) {
224 0 : continue;
225 : }
226 0 : eid_space_left -= left;
227 0 : eid_current_cnt += left;
228 : }
229 0 : (*eidCnt) = eid_current_cnt;
230 0 : return 0;
231 : }
232 :
233 0 : int HalGetUBEntityList(int phyId, UEList *ueList)
234 : {
235 0 : if (ueList == NULL) {
236 0 : return 0;
237 : }
238 0 : (void)memset_s(ueList, sizeof(UEList), 0x00, sizeof(UEList));
239 0 : unsigned int logicId = 0;
240 0 : if (hal_get_logicid_from_phyid((unsigned int)phyId, &logicId) != 0) {
241 0 : return -1;
242 : }
243 0 : int ret = dcmiv2_get_urma_device_cnt((int)logicId, &ueList->ueNum);
244 0 : if (ret != 0) {
245 0 : return ret;
246 : }
247 0 : for (size_t i = 0; i < ueList->ueNum; ++i) {
248 0 : int num = MAX_EID_PER_UE;
249 0 : ret = dcmiv2_get_eid_list_by_urma_dev_index((int)logicId, i,
250 0 : ueList->ueList[i].eidList, &num);
251 0 : if (ret != 0) {
252 0 : continue;
253 : }
254 0 : ueList->ueList[i].eidNum = (unsigned int)num;
255 : }
256 0 : return 0;
257 : }
258 :
259 0 : int hal_get_device_pcie_info(int phyId, struct dcmi_pcie_info_all* pcieInfo)
260 : {
261 0 : unsigned int logicId = 0;
262 0 : if (hal_get_logicid_from_phyid((unsigned int)phyId, &logicId) != 0) {
263 0 : return -1;
264 : }
265 0 : return dcmiv2_get_device_pcie_info(logicId, pcieInfo);
266 : }
267 :
268 0 : int hal_get_spod_info(int phyId, struct dcmi_spod_info* spodInfo)
269 : {
270 0 : unsigned int logicId = 0;
271 0 : if (hal_get_logicid_from_phyid((unsigned int)phyId, &logicId) != 0) {
272 0 : return -1;
273 : }
274 0 : int64_t spodId = 0;
275 0 : int64_t serverId = 0;
276 0 : int64_t chassisId = 0;
277 0 : int64_t spodType = 0;
278 0 : int ret1 = halGetDeviceInfo(logicId, MODULE_TYPE_SYSTEM, INFO_TYPE_SPOD_ID, &spodId);
279 0 : int ret2 = halGetDeviceInfo(logicId, MODULE_TYPE_SYSTEM, INFO_TYPE_SERVER_ID, &serverId);
280 0 : int ret3 = halGetDeviceInfo(logicId, MODULE_TYPE_SYSTEM, INFO_TYPE_CHASSI_ID, &chassisId);
281 0 : int ret4 = halGetDeviceInfo(logicId, MODULE_TYPE_SYSTEM, INFO_TYPE_SPOD_TYPE, &spodType);
282 0 : if (ret1 != 0 || ret2 != 0 || ret3 != 0 || ret4 != 0) {
283 0 : return -1;
284 : }
285 0 : spodInfo->super_pod_id = (unsigned int)spodId;
286 0 : spodInfo->server_index = (unsigned int)serverId;
287 0 : spodInfo->chassis_id = (unsigned int)chassisId;
288 0 : spodInfo->super_pod_type = (unsigned int)spodType;
289 0 : return 0;
290 : }
291 :
292 0 : int hal_get_npu_count()
293 : {
294 : #define MAX_NPU_COUNT (64)
295 : #define MAX_DAVINCI_DEV_LEN (64)
296 0 : int count = 0;
297 0 : for (int i = 0; i < MAX_NPU_COUNT; ++i) {
298 0 : char davinci_dev[MAX_DAVINCI_DEV_LEN] = {0};
299 0 : sprintf_s(davinci_dev, sizeof(davinci_dev), "/dev/davinci%d", i);
300 0 : if (access(davinci_dev, F_OK) == 0) {
301 0 : count++;
302 : }
303 : }
304 0 : return count;
305 : }
306 :
307 19 : int hal_get_logicid_from_phyid(unsigned int phyId, unsigned int* logicId)
308 : {
309 19 : if (load_dcmi() != 0) {
310 1 : return -1;
311 : }
312 18 : int userDevId = -1;
313 18 : int ret = aclrtGetUserDevIdByPhyDevId((int)phyId, &userDevId);
314 18 : if (ret != 0) {
315 0 : return -1;
316 : }
317 18 : int value = -1;
318 18 : ret = aclrtGetLogicDevIdByUserDevId(userDevId, &value);
319 18 : if (ret != 0) {
320 0 : return -1;
321 : }
322 18 : *logicId = (unsigned int)value;
323 18 : return 0;
324 : }
325 :
326 0 : int hal_get_userdevid_by_phyid(int phyId, int *userDevId)
327 : {
328 0 : if (load_dcmi() != 0) {
329 0 : return -1;
330 : }
331 0 : return aclrtGetUserDevIdByPhyDevId(phyId, userDevId);
332 : }
333 :
334 : // 去除字符串首尾的空白字符
335 0 : static char* trim_whitespace(char *str) {
336 : char *end;
337 :
338 : // 去除开头空格
339 0 : while(isspace((unsigned char)*str)){
340 0 : str++;
341 : }
342 : // 如果字符串全是空格,返回空字符串
343 0 : if(*str == 0) {
344 0 : return str;
345 : }
346 :
347 : // 去除结尾空格
348 0 : end = str + strlen(str) - 1;
349 0 : while(end > str && isspace((unsigned char)*end)) {
350 0 : end--;
351 : }
352 : // 添加字符串结束符
353 0 : end[1] = '\0';
354 0 : return str;
355 : }
356 :
357 : /**
358 : * @brief 解析ascend_install.info文件,获取指定key的value
359 : * @param value_buf 存储结果的缓冲区
360 : * @param buf_size 缓冲区大小
361 : * @return 成功返回0,失败返回-1值
362 : */
363 0 : int hal_get_driver_install_path(char *value_buf, size_t buf_size) {
364 0 : FILE *fp = NULL;
365 0 : char *line = NULL;
366 0 : size_t len = 0;
367 : ssize_t read;
368 : // 参数合法性检查
369 0 : if (value_buf == NULL || buf_size == 0) {
370 0 : return -1;
371 : }
372 : // 初始化缓冲区
373 0 : value_buf[0] = '\0';
374 :
375 : // 打开文件
376 0 : fp = fopen("/etc/ascend_install.info", "r");
377 0 : if (fp == NULL) {
378 0 : if (strcpy_s(value_buf, buf_size, DRIVER_DRFAULT_INSTALL_PATH) != 0) {
379 0 : return -1;
380 : }
381 0 : return 0;
382 : }
383 :
384 : // 逐行读取文件
385 0 : while ((read = getline(&line, &len, fp)) != -1) {
386 : // 去除换行符
387 0 : char *newline = strchr(line, '\n');
388 0 : if (newline) *newline = '\0';
389 :
390 : // 查找等号位置
391 0 : char *equal_sign = strchr(line, '=');
392 0 : if (equal_sign == NULL) {
393 0 : continue; // 跳过没有等号的行
394 : }
395 :
396 : // 分割key和value
397 0 : *equal_sign = '\0';
398 0 : char *key = trim_whitespace(line);
399 0 : char *value = trim_whitespace(equal_sign + 1);
400 :
401 : // 匹配目标key
402 0 : if (strcmp(key, TARGET_KEY) == 0) {
403 : // 检查缓冲区大小
404 0 : if (strlen(value) + 1 > buf_size) {
405 0 : break;
406 : }
407 : // 复制value到缓冲区
408 0 : errno_t ret = strcpy_s(value_buf, buf_size, value);
409 0 : if (ret != 0) {
410 0 : break;
411 : }
412 0 : value_buf[buf_size - 1] = '\0';
413 0 : break;
414 : }
415 : }
416 :
417 : // 释放资源
418 0 : if (line) {
419 0 : free(line);
420 : }
421 0 : if (fp) {
422 0 : fclose(fp);
423 : }
424 0 : if (strlen(value_buf) == 0) {
425 : // 默认值兜底
426 0 : if (strcpy_s(value_buf, buf_size, DRIVER_DRFAULT_INSTALL_PATH) != 0) {
427 0 : return -1;
428 : }
429 : }
430 0 : return 0;
431 : }
|