// Copyright(c) 2019-2020, Intel Corporation // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are met: // // * Redistributions of source code must retain the above copyright notice, // this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above copyright notice, // this list of conditions and the following disclaimer in the documentation // and/or other materials provided with the distribution. // * Neither the name of Intel Corporation nor the names of its contributors // may be used to endorse or promote products derived from this software // without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE // POSSIBILITY OF SUCH DAMAGE. #ifdef HAVE_CONFIG_H #include #endif // HAVE_CONFIG_H #ifndef __USE_GNU #define __USE_GNU #endif #ifndef _GNU_SOURCE #define _GNU_SOURCE #endif #include #include "fpgainfo.h" #include #include #include #include #include #include #include #include #include #include #include #include "board.h" static pthread_mutex_t board_plugin_lock = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP; // Board plug-in table static platform_data platform_data_table[] = { { 0x8086, 0x09c4, "libboard_rc.so", NULL }, { 0x8086, 0x09c5, "libboard_rc.so", NULL }, { 0x8086, 0x0b30, "libboard_vc.so", NULL }, { 0x8086, 0x0b31, "libboard_vc.so", NULL }, { 0x8086, 0x0b2b, "libboard_dc.so", NULL }, { 0x8086, 0x0b2c, "libboard_dc.so", NULL }, { 0, 0, NULL, NULL }, }; void *find_plugin(const char *libpath) { char plugin_path[PATH_MAX]; const char *search_paths[] = { OPAE_MODULE_SEARCH_PATHS }; unsigned i; void *dl_handle; for (i = 0 ; i < sizeof(search_paths) / sizeof(search_paths[0]) ; ++i) { snprintf(plugin_path, sizeof(plugin_path), "%s%s", search_paths[i], libpath); dl_handle = dlopen(plugin_path, RTLD_LAZY | RTLD_LOCAL); if (dl_handle) return dl_handle; } return NULL; } fpga_result load_board_plugin(fpga_token token, void **dl_handle) { fpga_result res = FPGA_OK; fpga_result resval = FPGA_OK; fpga_properties props = NULL; uint16_t vendor_id = 0; uint16_t device_id = 0; int i = 0; if (token == NULL || dl_handle == NULL) { OPAE_ERR("Invalid input parameter"); return FPGA_INVALID_PARAM; } res = fpgaGetProperties(token, &props); if (res != FPGA_OK) { OPAE_ERR("Failed to get properties\n"); return FPGA_INVALID_PARAM; } res = fpgaPropertiesGetDeviceID(props, &device_id); if (res != FPGA_OK) { OPAE_ERR("Failed to get device ID\n"); resval = res; goto destroy; } res = fpgaPropertiesGetVendorID(props, &vendor_id); if (res != FPGA_OK) { OPAE_ERR("Failed to get vendor ID\n"); resval = res; goto destroy; } if (pthread_mutex_lock(&board_plugin_lock) != 0) { OPAE_ERR("pthread mutex lock failed \n"); resval = FPGA_EXCEPTION; goto destroy; } for (i = 0; platform_data_table[i].board_plugin; ++i) { if (platform_data_table[i].device_id == device_id && platform_data_table[i].vendor_id == vendor_id) { // Loaded lib or found if (platform_data_table[i].dl_handle) { *dl_handle = platform_data_table[i].dl_handle; resval = FPGA_OK; goto unlock_destroy; } platform_data_table[i].dl_handle = find_plugin(platform_data_table[i].board_plugin); if (!platform_data_table[i].dl_handle) { char *err = dlerror(); OPAE_ERR("Failed to load \"%s\" %s", platform_data_table[i].board_plugin, err ? err : ""); resval = FPGA_EXCEPTION; goto unlock_destroy; } else { // Dynamically loaded board module *dl_handle = platform_data_table[i].dl_handle; resval = FPGA_OK; goto unlock_destroy; } } //end if } // end for unlock_destroy: if (pthread_mutex_unlock(&board_plugin_lock) != 0) { OPAE_ERR("pthread mutex unlock failed \n"); resval = FPGA_EXCEPTION; } destroy: res = fpgaDestroyProperties(&props); if (res != FPGA_OK) { OPAE_ERR("Failed to Destroy Object"); } if (*dl_handle == NULL) { OPAE_MSG("Failed to load board module"); resval = FPGA_EXCEPTION; } return resval; } int unload_board_plugin(void) { int i = 0; fpga_result res = FPGA_OK; fpga_result resval = FPGA_OK; if (pthread_mutex_lock(&board_plugin_lock) != 0) { OPAE_ERR("pthread mutex lock failed \n"); return FPGA_EXCEPTION; } for (i = 0; platform_data_table[i].board_plugin; ++i) { if (platform_data_table[i].dl_handle) { res = dlclose(platform_data_table[i].dl_handle); if (res) { char *err = dlerror(); OPAE_ERR("dlclose failed with %d %s", res, err ? err : ""); resval = FPGA_EXCEPTION; } else { platform_data_table[i].dl_handle = NULL; } } //end if } // end for if (pthread_mutex_unlock(&board_plugin_lock) != 0) { OPAE_ERR("pthread mutex unlock failed \n"); resval = FPGA_EXCEPTION; } return resval; } /* * Print help */ void mac_help(void) { printf("\nPrint MAC information\n" " fpgainfo mac [-h]\n" " -h,--help Print this help\n" "\n"); } #define MAC_GETOPT_STRING ":h" int parse_mac_args(int argc, char *argv[]) { struct option longopts[] = { {"help", no_argument, NULL, 'h'}, {0, 0, 0, 0}, }; int getopt_ret; int option_index; optind = 0; while (-1 != (getopt_ret = getopt_long(argc, argv, MAC_GETOPT_STRING, longopts, &option_index))) { const char *tmp_optarg = optarg; if (optarg && ('=' == *tmp_optarg)) { ++tmp_optarg; } switch (getopt_ret) { case 'h': /* help */ mac_help(); return -1; case ':': /* missing option argument */ fprintf(stderr, "Missing option argument\n"); mac_help(); return -1; case '?': default: /* invalid option */ fprintf(stderr, "Invalid cmdline options\n"); mac_help(); return -1; } } return 0; } fpga_result mac_filter(fpga_properties *filter, int argc, char *argv[]) { fpga_result res = FPGA_INVALID_PARAM; if (0 == parse_mac_args(argc, argv)) { res = fpgaPropertiesSetObjectType(*filter, FPGA_DEVICE); fpgainfo_print_err("Setting type to FPGA_DEVICE", res); } return res; } fpga_result mac_command(fpga_token *tokens, int num_tokens, int argc, char *argv[]) { (void)argc; (void)argv; fpga_result res = FPGA_OK; fpga_properties props; int i = 0; for (i = 0; i < num_tokens; ++i) { res = fpgaGetProperties(tokens[i], &props); if (res != FPGA_OK) { OPAE_ERR("Failed to get properties\n"); continue; } fpgainfo_board_info(tokens[i]); fpgainfo_print_common("//****** MAC ******//", props); res = mac_info(tokens[i]); if (res != FPGA_OK) { printf("mac info is not supported\n"); } } return FPGA_OK; } //phy /* * Print help */ void phy_help(void) { printf("\nPrint PHY information\n" " fpgainfo phy [-h] [-G ]\n" " -h,--help Print this help\n" " -G,--group Select PHY group {0,1,all}\n" "\n"); } #define PHY_GETOPT_STRING ":G:h" int group_num; int parse_phy_args(int argc, char *argv[]) { struct option longopts[] = { {"group", required_argument, NULL, 'G'}, {"help", no_argument, NULL, 'h'}, {0, 0, 0, 0}, }; int getopt_ret; int option_index; /* default configuration */ group_num = -1; optind = 0; while (-1 != (getopt_ret = getopt_long(argc, argv, PHY_GETOPT_STRING, longopts, &option_index))) { const char *tmp_optarg = optarg; if (optarg && ('=' == *tmp_optarg)) { ++tmp_optarg; } switch (getopt_ret) { case 'G': if (NULL == tmp_optarg) { fprintf(stderr, "Invalid argument group\n"); return -1; } if (!strcmp("0", tmp_optarg)) { group_num = 0; } else if (!strcmp("1", tmp_optarg)) { group_num = 1; } else if (!strcmp("all", tmp_optarg)) { group_num = -1; } else { fprintf(stderr, "Invalid argument '%s' of option group\n", tmp_optarg); return -1; } break; case 'h': /* help */ phy_help(); return -1; case ':': /* missing option argument */ fprintf(stderr, "Missing option argument\n"); phy_help(); return -1; case '?': default: /* invalid option */ fprintf(stderr, "Invalid cmdline options\n"); phy_help(); return -1; } } return 0; } fpga_result phy_filter(fpga_properties *filter, int argc, char *argv[]) { fpga_result res = FPGA_INVALID_PARAM; if (0 == parse_phy_args(argc, argv)) { res = fpgaPropertiesSetObjectType(*filter, FPGA_DEVICE); fpgainfo_print_err("setting type to FPGA_DEVICE", res); } return res; } fpga_result phy_command(fpga_token *tokens, int num_tokens, int argc, char *argv[]) { (void)argc; (void)argv; fpga_result res = FPGA_OK; fpga_properties props; int i = 0; for (i = 0; i < num_tokens; ++i) { res = fpgaGetProperties(tokens[i], &props); if (res != FPGA_OK) { OPAE_ERR("Failed to get properties\n"); continue; } fpgainfo_board_info(tokens[i]); fpgainfo_print_common("//****** PHY ******//", props); res = phy_group_info(tokens[i]); if (res != FPGA_OK) { printf("phy group info is not supported\n"); } } return FPGA_OK; } // prints board version info fpga_result fpgainfo_board_info(fpga_token token) { fpga_result res = FPGA_OK; void *dl_handle = NULL; // Board version fpga_result(*print_board_info)(fpga_token token); res = load_board_plugin(token, &dl_handle); if (res != FPGA_OK) { OPAE_MSG("Failed to load board plugin\n"); goto out; } print_board_info = dlsym(dl_handle, "print_board_info"); if (print_board_info) { res = print_board_info(token); } else { OPAE_ERR("No print_board_info entry point:%s\n", dlerror()); res = FPGA_NOT_FOUND; } out: return res; } // Prints mac info fpga_result mac_info(fpga_token token) { fpga_result res = FPGA_OK; void *dl_handle = NULL; // mac information fpga_result(*print_mac_info)(fpga_token token); res = load_board_plugin(token, &dl_handle); if (res != FPGA_OK) { OPAE_MSG("Failed to load board plugin\n"); goto out; } print_mac_info = dlsym(dl_handle, "print_mac_info"); if (print_mac_info) { res = print_mac_info(token); } else { OPAE_MSG("No print_mac_info entry point:%s\n", dlerror()); res = FPGA_NOT_FOUND; } out: return res; } // prints PHY group info fpga_result phy_group_info(fpga_token token) { fpga_result res = FPGA_OK; void *dl_handle = NULL; // phy group info fpga_result(*print_phy_info)(fpga_token token); res = load_board_plugin(token, &dl_handle); if (res != FPGA_OK) { OPAE_MSG("Failed to load board plugin\n"); goto out; } print_phy_info = dlsym(dl_handle, "print_phy_info"); if (print_phy_info) { res = print_phy_info(token); } else { OPAE_MSG("No print_phy_info entry point:%s\n", dlerror()); res = FPGA_NOT_FOUND; } out: return res; } void sec_help(void) { printf("\nPrint security information\n" " fpgainfo security [-h]\n" " -h,--help Print this help\n" "\n"); } #define SEC_GETOPT_STRING ":h" int parse_sec_args(int argc, char *argv[]) { struct option longopts[] = { {"help", no_argument, NULL, 'h'}, {0, 0, 0, 0}, }; int getopt_ret; int option_index; optind = 0; while (-1 != (getopt_ret = getopt_long(argc, argv, SEC_GETOPT_STRING, longopts, &option_index))) { const char *tmp_optarg = optarg; if (optarg && ('=' == *tmp_optarg)) { ++tmp_optarg; } switch (getopt_ret) { case 'h': /* help */ mac_help(); return -1; case ':': /* missing option argument */ fprintf(stderr, "Missing option argument\n"); mac_help(); return -1; case '?': default: /* invalid option */ fprintf(stderr, "Invalid cmdline options\n"); mac_help(); return -1; } } return 0; } fpga_result sec_filter(fpga_properties *filter, int argc, char *argv[]) { fpga_result res = FPGA_INVALID_PARAM; if (0 == parse_sec_args(argc, argv)) { res = fpgaPropertiesSetObjectType(*filter, FPGA_DEVICE); fpgainfo_print_err("Setting type to FPGA_DEVICE", res); } return res; } fpga_result sec_command(fpga_token *tokens, int num_tokens, int argc, char *argv[]) { (void)argc; (void)argv; fpga_result res = FPGA_OK; fpga_properties props; int i = 0; for (i = 0; i < num_tokens; ++i) { res = fpgaGetProperties(tokens[i], &props); if (res != FPGA_OK) { OPAE_ERR("Failed to get properties\n"); continue; } fpgainfo_board_info(tokens[i]); fpgainfo_print_common("//****** MAC ******//", props); res = sec_info(tokens[i]); if (res != FPGA_OK) { printf("mac info is not supported\n"); } } return FPGA_OK; } // Prints Sec info fpga_result sec_info(fpga_token token) { fpga_result res = FPGA_OK; void *dl_handle = NULL; // Sec information fpga_result(*print_sec_info)(fpga_token token); res = load_board_plugin(token, &dl_handle); if (res != FPGA_OK) { OPAE_MSG("Failed to load board plugin\n"); goto out; } print_sec_info = dlsym(dl_handle, "print_sec_info"); if (print_sec_info) { res = print_sec_info(token); } else { OPAE_MSG("No print_sec_info entry point:%s\n", dlerror()); res = FPGA_NOT_FOUND; } out: return res; }