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