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