int dhd_check_module_cid(dhd_pub_t *dhd) { int ret = -1; unsigned char cis_buf[CIS_BUF_SIZE] = {0}; const char *cidfilepath = CIDINFO; cis_rw_t *cish = (cis_rw_t *)&cis_buf[8]; int idx, max; vid_info_t *cur_info; unsigned char *vid_start; unsigned char vid_length; #if defined(BCM4334_CHIP) || defined(BCM4335_CHIP) const char *revfilepath = REVINFO; #ifdef BCM4334_CHIP int flag_b3; #else char rev_str[10] = {0}; #endif /* BCM4334_CHIP */ #endif /* BCM4334_CHIP || BCM4335_CHIP */ /* Try reading out from CIS */ cish->source = 0; cish->byteoff = 0; cish->nbytes = sizeof(cis_buf); strcpy(cis_buf, "cisdump"); ret = dhd_wl_ioctl_cmd(dhd, WLC_GET_VAR, cis_buf, sizeof(cis_buf), 0, 0); if (ret < 0) { DHD_ERROR(("%s: CIS reading failed, err=%d\n", __FUNCTION__, ret)); return ret; } DHD_ERROR(("%s: CIS reading success, ret=%d\n", __FUNCTION__, ret)); #ifdef DUMP_CIS dhd_dump_cis(cis_buf, 48); #endif max = sizeof(cis_buf) - 4; for (idx = 0; idx < max; idx++) { if (cis_buf[idx] == CIS_TUPLE_START) { if (cis_buf[idx + 2] == CIS_TUPLE_VENDOR) { vid_length = cis_buf[idx + 1]; vid_start = &cis_buf[idx + 3]; /* found CIS tuple */ break; } else { /* Go to next tuple if tuple value is not vendor type */ idx += (cis_buf[idx + 1] + 1); } } } if (idx < max) { max = sizeof(vid_info) / sizeof(vid_info_t); for (idx = 0; idx < max; idx++) { cur_info = &vid_info[idx]; if ((cur_info->vid_length == vid_length) && (cur_info->vid_length != 0) && (memcmp(cur_info->vid, vid_start, cur_info->vid_length - 1) == 0)) goto write_cid; } } /* find default nvram, if exist */ DHD_ERROR(("%s: cannot find CIS TUPLE set as default\n", __FUNCTION__)); max = sizeof(vid_info) / sizeof(vid_info_t); for (idx = 0; idx < max; idx++) { cur_info = &vid_info[idx]; if (cur_info->vid_length == 0) goto write_cid; } DHD_ERROR(("%s: cannot find default CID\n", __FUNCTION__)); return -1; write_cid: DHD_ERROR(("CIS MATCH FOUND : %s\n", cur_info->vname)); dhd_write_cid_file(cidfilepath, cur_info->vname, strlen(cur_info->vname)+1); #if defined(BCM4334_CHIP) /* Try reading out from OTP to distinguish B2 or B3 */ memset(cis_buf, 0, sizeof(cis_buf)); cish = (cis_rw_t *)&cis_buf[8]; cish->source = 0; cish->byteoff = 0; cish->nbytes = sizeof(cis_buf); strcpy(cis_buf, "otpdump"); ret = dhd_wl_ioctl_cmd(dhd, WLC_GET_VAR, cis_buf, sizeof(cis_buf), 0, 0); if (ret < 0) { DHD_ERROR(("%s: OTP reading failed, err=%d\n", __FUNCTION__, ret)); return ret; } /* otp 33th character is identifier for 4334B3 */ cis_buf[34] = '\0'; flag_b3 = bcm_atoi(&cis_buf[33]); if (flag_b3 & 0x1) { DHD_ERROR(("REV MATCH FOUND : 4334B3, %c\n", cis_buf[33])); dhd_write_cid_file(revfilepath, "4334B3", 6); } #endif /* BCM4334_CHIP */ #if defined(BCM4335_CHIP) DHD_TRACE(("%s: BCM4335 Multiple Revision Check\n", __FUNCTION__)); if (concate_revision(dhd->bus, rev_str, sizeof(rev_str), rev_str, sizeof(rev_str)) < 0) { DHD_ERROR(("%s: fail to concate revision\n", __FUNCTION__)); ret = -1; } else { if (strstr(rev_str, "_a0")) { DHD_ERROR(("REV MATCH FOUND : 4335A0\n")); dhd_write_cid_file(revfilepath, "BCM4335A0", 9); } else { DHD_ERROR(("REV MATCH FOUND : 4335B0\n")); dhd_write_cid_file(revfilepath, "BCM4335B0", 9); } } #endif /* BCM4335_CHIP */ return ret; }
int dhd_check_module_cid(dhd_pub_t *dhd) { int ret = -1; unsigned char cis_buf[CIS_BUF_SIZE] = {0}; const char *cidfilepath = CIDINFO; cis_rw_t *cish = (cis_rw_t *)&cis_buf[8]; int idx, max; vid_info_t *cur_info; unsigned char *vid_start = NULL; unsigned char vid_length = 0; #ifdef SUPPORT_MULTIPLE_BOARDTYPE board_info_t *cur_b_info = NULL; board_info_t *vendor_b_info = NULL; unsigned char *btype_start; unsigned char boardtype_len = 0; #endif /* SUPPORT_MULTIPLE_BOARDTYPE */ unsigned char cid_info[MAX_VNAME_LEN + MAX_BNAME_LEN]; bool found = FALSE; #if defined(BCM4334_CHIP) || defined(BCM4335_CHIP) const char *revfilepath = REVINFO; #ifdef BCM4334_CHIP int flag_b3; #else char rev_str[10] = {0}; #endif /* BCM4334_CHIP */ #endif /* BCM4334_CHIP || BCM4335_CHIP */ /* Try reading out from CIS */ cish->source = 0; cish->byteoff = 0; cish->nbytes = sizeof(cis_buf); strcpy(cis_buf, "cisdump"); ret = dhd_wl_ioctl_cmd(dhd, WLC_GET_VAR, cis_buf, sizeof(cis_buf), 0, 0); if (ret < 0) { DHD_INFO(("[WIFI_SEC] %s: CIS reading failed, ret=%d\n", __FUNCTION__, ret)); return ret; } DHD_ERROR(("[WIFI_SEC] %s: CIS reading success, ret=%d\n", __FUNCTION__, ret)); #ifdef DUMP_CIS dhd_dump_cis(cis_buf, 48); #endif max = sizeof(cis_buf); idx = find_tuple_from_otp(cis_buf, max, CIS_TUPLE_TAG_VENDOR, &vid_length); if (idx > 0) { found = TRUE; vid_start = &cis_buf[idx]; } if (found) { max = sizeof(vid_info) / sizeof(vid_info_t); for (idx = 0; idx < max; idx++) { cur_info = &vid_info[idx]; #if defined(BCM4358_CHIP) if (cur_info->vid_length == 6 && vid_length == 6) { if (cur_info->vid[0] == vid_start[0] && cur_info->vid[3] == vid_start[3] && cur_info->vid[4] == vid_start[4]) goto check_board_type; } #endif /* BCM4358_CHIP */ if ((cur_info->vid_length == vid_length) && (cur_info->vid_length != 0) && (memcmp(cur_info->vid, vid_start, cur_info->vid_length - 1) == 0)) goto check_board_type; } } /* find default nvram, if exist */ DHD_ERROR(("[WIFI_SEC] %s: cannot find CIS TUPLE set as default\n", __FUNCTION__)); max = sizeof(vid_info) / sizeof(vid_info_t); for (idx = 0; idx < max; idx++) { cur_info = &vid_info[idx]; if (cur_info->vid_length == 0) goto write_cid; } DHD_ERROR(("[WIFI_SEC] %s: cannot find default CID\n", __FUNCTION__)); return -1; check_board_type: #ifdef SUPPORT_MULTIPLE_BOARDTYPE max = sizeof(cis_buf) - 4; for (idx = 0; idx < max; idx++) { if (cis_buf[idx] == CIS_TUPLE_TAG_START && cis_buf[idx + 2] == CIS_TUPLE_TAG_BOARDTYPE) { boardtype_len = cis_buf[idx + 1]; btype_start = &cis_buf[idx + 3]; /* Check buffer overflow */ if (&cis_buf[idx + 1] + boardtype_len <= &cis_buf[CIS_BUF_SIZE - 1]) { DHD_INFO(("[WIFI_SEC] %s: board type found.\n", __FUNCTION__)); break; } else { boardtype_len = 0; } } } if (strcmp(cur_info->vname, "semco") == 0) { vendor_b_info = semco_board_info; max = sizeof(semco_board_info) / sizeof(board_info_t); } else if (strcmp(cur_info->vname, "murata") == 0) { vendor_b_info = murata_board_info; max = sizeof(murata_board_info) / sizeof(board_info_t); } else { max = 0; } if (boardtype_len) { for (idx = 0; idx < max; idx++) { cur_b_info = vendor_b_info; if ((cur_b_info->b_len == boardtype_len) && (cur_b_info->b_len != 0) && (memcmp(cur_b_info->btype, btype_start, cur_b_info->b_len - 1) == 0)) { DHD_INFO(("[WIFI_SEC] %s : board type name : %s\n", __FUNCTION__, cur_b_info->bname)); break; } cur_b_info = NULL; vendor_b_info++; } } #endif /* SUPPORT_MULTIPLE_BOARDTYPE */ write_cid: #ifdef SUPPORT_MULTIPLE_BOARDTYPE if (cur_b_info && cur_b_info->b_len > 0) { strcpy(cid_info, cur_info->vname); strcpy(cid_info + strlen(cur_info->vname), cur_b_info->bname); } else #endif /* SUPPORT_MULTIPLE_BOARDTYPE */ strcpy(cid_info, cur_info->vname); DHD_ERROR(("[WIFI_SEC] CIS MATCH FOUND : %s\n", cid_info)); dhd_write_cid_file(cidfilepath, cid_info, strlen(cid_info)+1); #if defined(BCM4334_CHIP) /* Try reading out from OTP to distinguish B2 or B3 */ memset(cis_buf, 0, sizeof(cis_buf)); cish = (cis_rw_t *)&cis_buf[8]; cish->source = 0; cish->byteoff = 0; cish->nbytes = sizeof(cis_buf); strcpy(cis_buf, "otpdump"); ret = dhd_wl_ioctl_cmd(dhd, WLC_GET_VAR, cis_buf, sizeof(cis_buf), 0, 0); if (ret < 0) { DHD_ERROR(("[WIFI_SEC] %s: OTP reading failed, err=%d\n", __FUNCTION__, ret)); return ret; } /* otp 33th character is identifier for 4334B3 */ cis_buf[34] = '\0'; flag_b3 = bcm_atoi(&cis_buf[33]); if (flag_b3 & 0x1) { DHD_ERROR(("[WIFI_SEC] REV MATCH FOUND : 4334B3, %c\n", cis_buf[33])); dhd_write_cid_file(revfilepath, "4334B3", 6); } #endif /* BCM4334_CHIP */ #if defined(BCM4335_CHIP) DHD_TRACE(("[WIFI_SEC] %s: BCM4335 Multiple Revision Check\n", __FUNCTION__)); if (concate_revision(dhd->bus, rev_str, rev_str) < 0) { DHD_ERROR(("[WIFI_SEC] %s: fail to concate revision\n", __FUNCTION__)); ret = -1; } else { if (strstr(rev_str, "_a0")) { DHD_ERROR(("[WIFI_SEC] REV MATCH FOUND : 4335A0\n")); dhd_write_cid_file(revfilepath, "BCM4335A0", 9); } else { DHD_ERROR(("[WIFI_SEC] REV MATCH FOUND : 4335B0\n")); dhd_write_cid_file(revfilepath, "BCM4335B0", 9); } } #endif /* BCM4335_CHIP */ return ret; }