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