tizen 2.4 release
[profile/mobile/platform/kernel/linux-3.10-sc7730.git] / drivers / net / wireless / bcmdhd / dhd_custom_sec.c
1 /*
2  * Customer HW 4 dependant file
3  *
4  * Copyright (C) 1999-2015, Broadcom Corporation
5  * 
6  *      Unless you and Broadcom execute a separate written software license
7  * agreement governing use of this software, this software is licensed to you
8  * under the terms of the GNU General Public License version 2 (the "GPL"),
9  * available at http://www.broadcom.com/licenses/GPLv2.php, with the
10  * following added to such license:
11  * 
12  *      As a special exception, the copyright holders of this software give you
13  * permission to link this software with independent modules, and to copy and
14  * distribute the resulting executable under terms of your choice, provided that
15  * you also meet, for each linked independent module, the terms and conditions of
16  * the license of that module.  An independent module is a module which is not
17  * derived from this software.  The special exception does not apply to any
18  * modifications of the software.
19  * 
20  *      Notwithstanding the above, under no circumstances may you combine this
21  * software in any way with any other Broadcom software provided under a license
22  * other than the GPL, without Broadcom's express prior written consent.
23  *
24  * $Id: dhd_custom_sec.c 334946 2012-05-24 20:38:00Z $
25  */
26 #ifdef CUSTOMER_HW4
27 #include <typedefs.h>
28 #include <linuxver.h>
29 #include <osl.h>
30
31 #include <proto/ethernet.h>
32 #include <dngl_stats.h>
33 #include <bcmutils.h>
34 #include <dhd.h>
35 #include <dhd_dbg.h>
36 #include <dhd_linux.h>
37 #include <bcmdevs.h>
38
39 #include <linux/fcntl.h>
40 #include <linux/fs.h>
41
42 struct dhd_info;
43 extern int _dhd_set_mac_address(struct dhd_info *dhd,
44         int ifidx, struct ether_addr *addr);
45
46 struct cntry_locales_custom {
47         char iso_abbrev[WLC_CNTRY_BUF_SZ]; /* ISO 3166-1 country abbreviation */
48         char custom_locale[WLC_CNTRY_BUF_SZ]; /* Custom firmware locale */
49         int32 custom_locale_rev; /* Custom local revisin default -1 */
50 };
51
52 /* Locale table for sec */
53 const struct cntry_locales_custom translate_custom_table[] = {
54 #if defined(BCM4330_CHIP) || defined(BCM4334_CHIP) || defined(BCM43241_CHIP)
55         /* 4330/4334/43241 */
56         {"AR", "AR", 1},
57         {"AT", "AT", 1},
58         {"AU", "AU", 2},
59         {"BE", "BE", 1},
60         {"BG", "BG", 1},
61         {"BN", "BN", 1},
62         {"CA", "CA", 2},
63         {"CH", "CH", 1},
64         {"CY", "CY", 1},
65         {"CZ", "CZ", 1},
66         {"DE", "DE", 3},
67         {"DK", "DK", 1},
68         {"EE", "EE", 1},
69         {"ES", "ES", 1},
70         {"FI", "FI", 1},
71         {"FR", "FR", 1},
72         {"GB", "GB", 1},
73         {"GR", "GR", 1},
74         {"HR", "HR", 1},
75         {"HU", "HU", 1},
76         {"IE", "IE", 1},
77         {"IS", "IS", 1},
78         {"IT", "IT", 1},
79         {"JP", "JP", 5},
80         {"KR", "KR", 24},
81         {"KW", "KW", 1},
82         {"LI", "LI", 1},
83         {"LT", "LT", 1},
84         {"LU", "LU", 1},
85         {"LV", "LV", 1},
86         {"MT", "MT", 1},
87         {"NL", "NL", 1},
88         {"NO", "NO", 1},
89         {"PL", "PL", 1},
90         {"PT", "PT", 1},
91         {"PY", "PY", 1},
92         {"RO", "RO", 1},
93         {"RU", "RU", 13},
94         {"SE", "SE", 1},
95         {"SI", "SI", 1},
96         {"SK", "SK", 1},
97         {"TW", "TW", 2},
98 #ifdef BCM4330_CHIP
99         {"",   "XZ", 1},        /* Universal if Country code is unknown or empty */
100         {"IR", "XZ", 1},        /* Universal if Country code is IRAN, (ISLAMIC REPUBLIC OF) */
101         {"SD", "XZ", 1},        /* Universal if Country code is SUDAN */
102         {"SY", "XZ", 1},        /* Universal if Country code is SYRIAN ARAB REPUBLIC */
103         {"GL", "XZ", 1},        /* Universal if Country code is GREENLAND */
104         {"PS", "XZ", 1},        /* Universal if Country code is PALESTINIAN TERRITORY, OCCUPIED */
105         {"TL", "XZ", 1},        /* Universal if Country code is TIMOR-LESTE (EAST TIMOR) */
106         {"MH", "XZ", 1},        /* Universal if Country code is MARSHALL ISLANDS */
107         {"JO", "XZ", 1},        /* Universal if Country code is Jordan */
108         {"PG", "XZ", 1},        /* Universal if Country code is Papua New Guinea */
109         {"SA", "XZ", 1},        /* Universal if Country code is Saudi Arabia */
110         {"AF", "XZ", 1},        /* Universal if Country code is Afghanistan */
111         {"US", "US", 5},
112         {"UA", "UY", 0},
113         {"AD", "AL", 0},
114         {"CX", "AU", 2},
115         {"GE", "GB", 1},
116         {"ID", "MW", 0},
117         {"KI", "AU", 2},
118         {"NP", "SA", 0},
119         {"WS", "SA", 0},
120         {"LR", "BR", 0},
121         {"ZM", "IN", 0},
122         {"AN", "AG", 0},
123         {"AI", "AS", 0},
124         {"BM", "AS", 0},
125         {"DZ", "GB", 1},
126         {"LC", "AG", 0},
127         {"MF", "BY", 0},
128         {"GY", "CU", 0},
129         {"LA", "GB", 1},
130         {"LB", "BR", 0},
131         {"MA", "IL", 0},
132         {"MO", "BD", 0},
133         {"MW", "BD", 0},
134         {"QA", "BD", 0},
135         {"TR", "GB", 1},
136         {"TZ", "BF", 0},
137         {"VN", "BR", 0},
138         {"AE", "AZ", 0},
139         {"IQ", "GB", 1},
140         {"CN", "CL", 0},
141         {"MX", "MX", 1},
142 #else
143         /* 4334/43241 */
144         {"",   "XZ", 11},       /* Universal if Country code is unknown or empty */
145         {"IR", "XZ", 11},       /* Universal if Country code is IRAN, (ISLAMIC REPUBLIC OF) */
146         {"SD", "XZ", 11},       /* Universal if Country code is SUDAN */
147         {"SY", "XZ", 11},       /* Universal if Country code is SYRIAN ARAB REPUBLIC */
148         {"GL", "XZ", 11},       /* Universal if Country code is GREENLAND */
149         {"PS", "XZ", 11},       /* Universal if Country code is PALESTINIAN TERRITORY, OCCUPIED */
150         {"TL", "XZ", 11},       /* Universal if Country code is TIMOR-LESTE (EAST TIMOR) */
151         {"MH", "XZ", 11},       /* Universal if Country code is MARSHALL ISLANDS */
152         {"US", "US", 46},
153         {"UA", "UA", 8},
154         {"CO", "CO", 4},
155         {"ID", "ID", 1},
156         {"LA", "LA", 1},
157         {"LB", "LB", 2},
158         {"VN", "VN", 4},
159         {"MA", "MA", 1},
160         {"TR", "TR", 7},
161 #endif /* defined(BCM4330_CHIP) */
162 #ifdef BCM4334_CHIP
163         {"AE", "AE", 1},
164         {"MX", "MX", 1},
165 #endif /* defined(BCM4334_CHIP) */
166 #ifdef BCM43241_CHIP
167         {"AE", "AE", 6},
168         {"BD", "BD", 2},
169         {"CN", "CN", 38},
170         {"MX", "MX", 20},
171 #endif /* defined(BCM43241_CHIP) */
172 #else  /* defined(BCM4330_CHIP) || defined(BCM4334_CHIP) || defined(BCM43241_CHIP) */
173         /* default ccode/regrev */
174         {"",   "XZ", 11},       /* Universal if Country code is unknown or empty */
175         {"IR", "XZ", 11},       /* Universal if Country code is IRAN, (ISLAMIC REPUBLIC OF) */
176         {"SD", "XZ", 11},       /* Universal if Country code is SUDAN */
177         {"SY", "XZ", 11},       /* Universal if Country code is SYRIAN ARAB REPUBLIC */
178         {"PS", "XZ", 11},       /* Universal if Country code is PALESTINIAN TERRITORY, OCCUPIED */
179         {"TL", "XZ", 11},       /* Universal if Country code is TIMOR-LESTE (EAST TIMOR) */
180         {"MH", "XZ", 11},       /* Universal if Country code is MARSHALL ISLANDS */
181         {"GL", "GP", 2},
182         {"AL", "AL", 2},
183         {"DZ", "GB", 6},
184         {"AS", "AS", 12},
185         {"AI", "AI", 1},
186         {"AF", "AD", 0},
187         {"AG", "AG", 2},
188         {"AR", "AU", 6},
189         {"AW", "AW", 2},
190         {"AU", "AU", 6},
191         {"AT", "AT", 4},
192         {"AZ", "AZ", 2},
193         {"BS", "BS", 2},
194         {"BH", "BH", 4},
195         {"BD", "BD", 1},
196         {"BY", "BY", 3},
197         {"BE", "BE", 4},
198         {"BM", "BM", 12},
199         {"BA", "BA", 2},
200         {"BR", "BR", 2},
201         {"VG", "VG", 2},
202         {"BN", "BN", 4},
203         {"BG", "BG", 4},
204         {"KH", "KH", 2},
205         {"CA", "US", 0},
206         {"KY", "KY", 3},
207         {"CN", "CN", 38},
208         {"CO", "CO", 17},
209         {"CR", "CR", 17},
210         {"HR", "HR", 4},
211         {"CY", "CY", 4},
212         {"CZ", "CZ", 4},
213         {"DK", "DK", 4},
214         {"EE", "EE", 4},
215         {"ET", "ET", 2},
216         {"FI", "FI", 4},
217         {"FR", "FR", 5},
218         {"GF", "GF", 2},
219         {"DE", "DE", 7},
220         {"GR", "GR", 4},
221         {"GD", "GD", 2},
222         {"GP", "GP", 2},
223         {"GU", "GU", 30},
224         {"HK", "HK", 2},
225         {"HU", "HU", 4},
226         {"IS", "IS", 4},
227         {"IN", "IN", 3},
228         {"ID", "ID", 1},
229         {"IE", "IE", 5},
230         {"IL", "IL", 7},
231         {"IT", "IT", 4},
232         {"JP", "JP", 45},
233         {"JO", "JO", 3},
234         {"KE", "SA", 0},
235         {"KW", "KW", 5},
236         {"LA", "LA", 2},
237         {"LV", "LV", 4},
238         {"LB", "LB", 5},
239         {"LS", "LS", 2},
240         {"LI", "LI", 4},
241         {"LT", "LT", 4},
242         {"LU", "LU", 3},
243         {"MO", "SG", 0},
244         {"MK", "MK", 2},
245         {"MW", "MW", 1},
246         {"MY", "MY", 3},
247         {"MV", "MV", 3},
248         {"MT", "MT", 4},
249         {"MQ", "MQ", 2},
250         {"MR", "MR", 2},
251         {"MU", "MU", 2},
252         {"YT", "YT", 2},
253         {"MX", "MX", 44},
254         {"MD", "MD", 2},
255         {"MC", "MC", 1},
256         {"ME", "ME", 2},
257         {"MA", "MA", 2},
258         {"NL", "NL", 4},
259         {"AN", "GD", 2},
260         {"NZ", "NZ", 4},
261         {"NO", "NO", 4},
262         {"OM", "OM", 4},
263         {"PA", "PA", 17},
264         {"PG", "AU", 6},
265         {"PY", "PY", 2},
266         {"PE", "PE", 20},
267         {"PH", "PH", 5},
268         {"PL", "PL", 4},
269         {"PT", "PT", 4},
270         {"PR", "PR", 38},
271         {"RE", "RE", 2},
272         {"RO", "RO", 4},
273         {"SN", "MA", 2},
274         {"RS", "RS", 2},
275         {"SK", "SK", 4},
276         {"SI", "SI", 4},
277         {"ES", "ES", 4},
278         {"LK", "LK", 1},
279         {"SE", "SE", 4},
280         {"CH", "CH", 4},
281         {"TW", "TW", 1},
282         {"TH", "TH", 5},
283         {"TT", "TT", 3},
284         {"TR", "TR", 7},
285         {"AE", "AE", 6},
286         {"GB", "GB", 6},
287         {"UY", "VE", 3},
288         {"VI", "PR", 38},
289         {"VA", "VA", 2},
290         {"VE", "VE", 3},
291         {"VN", "VN", 4},
292         {"ZM", "LA", 2},
293         {"EC", "EC", 21},
294         {"SV", "SV", 25},
295         {"KR", "KR", 70},
296         {"RU", "RU", 13},
297         {"UA", "UA", 8},
298         {"GT", "GT", 1},
299         {"MN", "MN", 1},
300         {"NI", "NI", 2},
301         {"UZ", "MA", 2},
302         {"ZA", "ZA", 6},
303         {"EG", "EG", 13},
304         {"TN", "TN", 1},
305         {"AO", "AD", 0},
306         {"BT", "BJ", 0},
307         {"BW", "BJ", 0},
308         {"LY", "LI", 4},
309         {"BO", "NG", 0},
310         {"UM", "PR", 38},
311 #endif /* default ccode/regrev */
312 };
313
314 /* Customized Locale convertor
315 *  input : ISO 3166-1 country abbreviation
316 *  output: customized cspec
317 */
318 void get_customized_country_code(void *adapter, char *country_iso_code, wl_country_t *cspec)
319 {
320         int size, i;
321
322         size = ARRAYSIZE(translate_custom_table);
323
324         if (cspec == 0)
325                  return;
326
327         if (size == 0)
328                  return;
329
330         for (i = 0; i < size; i++) {
331                 if (strcmp(country_iso_code, translate_custom_table[i].iso_abbrev) == 0) {
332                         memcpy(cspec->ccode,
333                                 translate_custom_table[i].custom_locale, WLC_CNTRY_BUF_SZ);
334                         cspec->rev = translate_custom_table[i].custom_locale_rev;
335                         return;
336                 }
337         }
338         return;
339 }
340
341 #ifdef PLATFORM_SLP
342 #define CIDINFO "/opt/etc/.cid.info"
343 #define PSMINFO "/opt/etc/.psm.info"
344 #define MACINFO "/opt/etc/.mac.info"
345 #define MACINFO_EFS "/csa/.mac.info"
346 #define REVINFO "/opt/etc/.rev"
347 #define WIFIVERINFO "/opt/etc/.wifiver.info"
348 #define ANTINFO "/opt/etc/.ant.info"
349 #define WRMAC_BUF_SIZE 19
350 #else
351 #define MACINFO "/data/.mac.info"
352 #define MACINFO_EFS "/efs/wifi/.mac.info"
353 #define NVMACINFO "/data/.nvmac.info"
354 #define REVINFO "/data/.rev"
355 #define CIDINFO "/data/.cid.info"
356 #define PSMINFO "/data/.psm.info"
357 #define WIFIVERINFO "/data/.wifiver.info"
358 #define ANTINFO "/data/.ant.info"
359 #define WRMAC_BUF_SIZE 18
360 #endif /* PLATFORM_SLP */
361
362 #ifdef BCM4330_CHIP
363 #define CIS_BUF_SIZE            128
364 #elif defined(BCM4334_CHIP)
365 #define CIS_BUF_SIZE            256
366 #else
367 #define CIS_BUF_SIZE            512
368 #endif /* BCM4330_CHIP */
369
370 #define CIS_TUPLE_TAG_START             0x80
371 #define CIS_TUPLE_TAG_VENDOR            0x81
372 #define CIS_TUPLE_TAG_MACADDR           0x19
373 #define CIS_TUPLE_TAG_MACADDR_OFF       ((TLV_BODY_OFF) + (1))
374
375 #ifdef READ_MACADDR
376 int dhd_read_macaddr(struct dhd_info *dhd, struct ether_addr *mac)
377 {
378         struct file *fp      = NULL;
379         char macbuffer[WRMAC_BUF_SIZE]   = {0};
380         mm_segment_t oldfs   = {0};
381         char randommac[3]    = {0};
382         char buf[WRMAC_BUF_SIZE]         = {0};
383         char *filepath_efs       = MACINFO_EFS;
384         char *filepath_etc      = MACINFO;
385         int ret = 0;
386
387         fp = filp_open(filepath_efs, O_RDONLY, 0);
388         if (IS_ERR(fp)) {
389 start_readmac:
390                 /* File Doesn't Exist. Create and write mac addr. */
391                 fp = filp_open(filepath_efs, O_RDWR | O_CREAT, 0666);
392                 if (IS_ERR(fp)) {
393                         DHD_ERROR(("[WIFI_SEC] %s: File open error\n", filepath_efs));
394                         return -1;
395                 }
396                 oldfs = get_fs();
397                 set_fs(get_ds());
398
399                 /* Generating the Random Bytes for 3 last octects of the MAC address */
400                 get_random_bytes(randommac, 3);
401
402                 snprintf(macbuffer, sizeof(macbuffer),"%02X:%02X:%02X:%02X:%02X:%02X\n",
403                         0x00, 0x12, 0x34, randommac[0], randommac[1], randommac[2]);
404                 DHD_ERROR(("[WIFI_SEC] The Random Generated MAC ID: %s\n", macbuffer));
405
406                 if (fp->f_mode & FMODE_WRITE) {
407                         ret = fp->f_op->write(fp, (const char *)macbuffer,
408                         sizeof(macbuffer), &fp->f_pos);
409                         if (ret < 0)
410                                 DHD_ERROR(("[WIFI_SEC] MAC address [%s] Failed to write into File:"
411                                         " %s\n", macbuffer, filepath_efs));
412                         else
413                                 DHD_ERROR(("[WIFI_SEC] MAC address [%s] written into File: %s\n",
414                                         macbuffer, filepath_efs));
415                 }
416                 set_fs(oldfs);
417                 /* Reading the MAC Address from .mac.info file
418                    ( the existed file or just created file)
419                  */
420                 ret = kernel_read(fp, 0, buf, 18);
421         } else {
422                 /* Reading the MAC Address from
423                    .mac.info file( the existed file or just created file)
424                  */
425                 ret = kernel_read(fp, 0, buf, 19);
426                 /* to prevent abnormal string display
427                 * when mac address is displayed on the screen.
428                 */
429                 buf[17] = '\0';
430                 if (strncmp(buf, "00:00:00:00:00:00", 17) < 1) {
431                         DHD_ERROR(("[WIFI_SEC] goto start_readmac \r\n"));
432                         filp_close(fp, NULL);
433                         goto start_readmac;
434                 }
435         }
436
437         if (ret)
438                 sscanf(buf, "%02X:%02X:%02X:%02X:%02X:%02X",
439                         (unsigned int *)&(mac->octet[0]), (unsigned int *)&(mac->octet[1]),
440                         (unsigned int *)&(mac->octet[2]), (unsigned int *)&(mac->octet[3]),
441                         (unsigned int *)&(mac->octet[4]), (unsigned int *)&(mac->octet[5]));
442         else
443                 DHD_ERROR(("[WIFI_SEC] dhd_bus_start: Reading from the '%s' returns 0 bytes\n",
444                         filepath_efs));
445
446         if (fp)
447                 filp_close(fp, NULL);
448
449         buf[17] = '\n';
450
451         /* Writing Newly generated MAC ID to the Dongle */
452         if (_dhd_set_mac_address(dhd, 0, mac) == 0)
453                 DHD_INFO(("[WIFI_SEC] dhd_bus_start: MACID is overwritten\n"));
454         else
455                 DHD_ERROR(("[WIFI_SEC] dhd_bus_start: _dhd_set_mac_address() failed\n"));
456
457         /* Writing MAC ID to the /opt/etc/.mac.info */
458         fp = filp_open(filepath_etc, O_RDWR | O_CREAT, 0666);
459
460         if (IS_ERR(fp)) {
461                 DHD_ERROR(("[WIFI_SEC] %s: File open error\n", filepath_etc));
462                 return -1;
463         } else {
464                 oldfs = get_fs();
465                 set_fs(get_ds());
466
467                 if (fp->f_mode & FMODE_WRITE) {
468                         ret = fp->f_op->write(fp, (const char *)buf,
469                         sizeof(buf), &fp->f_pos);
470                         if (ret < 0)
471                                 DHD_ERROR(("[WIFI_SEC] Mac address [%s] Failed"
472                                 " to write into File: %s\n", buf, filepath_etc));
473                         else
474                                 DHD_INFO(("[WIFI_SEC] Mac address [%s] written"
475                                 " into File: %s\n", buf, filepath_etc));
476                 }
477                 set_fs(oldfs);
478                 filp_close(fp, NULL);
479         }
480         return 0;
481 }
482 #endif /* READ_MACADDR */
483
484 #ifdef RDWR_MACADDR
485 static int g_imac_flag;
486
487 enum {
488         MACADDR_NONE = 0,
489         MACADDR_MOD,
490         MACADDR_MOD_RANDOM,
491         MACADDR_MOD_NONE,
492         MACADDR_COB,
493         MACADDR_COB_RANDOM
494 };
495
496 int dhd_write_rdwr_macaddr(struct ether_addr *mac)
497 {
498         char *filepath_data = MACINFO;
499         char *filepath_efs = MACINFO_EFS;
500         struct file *fp_mac = NULL;
501         char buf[18]      = {0};
502         mm_segment_t oldfs    = {0};
503         int ret = -1;
504
505         if ((g_imac_flag != MACADDR_COB) && (g_imac_flag != MACADDR_MOD))
506                 return 0;
507
508         sprintf(buf, "%02X:%02X:%02X:%02X:%02X:%02X\n",
509                 mac->octet[0], mac->octet[1], mac->octet[2],
510                 mac->octet[3], mac->octet[4], mac->octet[5]);
511
512         /* /efs/wifi/.mac.info will be created */
513         fp_mac = filp_open(filepath_efs, O_RDWR | O_CREAT, 0666);
514         if (IS_ERR(fp_mac)) {
515                 DHD_ERROR(("[WIFI_SEC] %s: File open error\n", filepath_data));
516                 return -1;
517         }       else {
518                 oldfs = get_fs();
519                 set_fs(get_ds());
520
521                 if (fp_mac->f_mode & FMODE_WRITE) {
522                         ret = fp_mac->f_op->write(fp_mac, (const char *)buf,
523                                 sizeof(buf), &fp_mac->f_pos);
524                         if (ret < 0)
525                                 DHD_ERROR(("[WIFI_SEC] Mac address [%s] Failed"
526                                 " to write into File: %s\n", buf, filepath_data));
527                         else
528                                 DHD_INFO(("[WIFI_SEC] Mac address [%s] written"
529                                 " into File: %s\n", buf, filepath_data));
530                 }
531                 set_fs(oldfs);
532                 filp_close(fp_mac, NULL);
533         }
534         /* /data/.mac.info will be created */
535         fp_mac = filp_open(filepath_data, O_RDWR | O_CREAT, 0666);
536         if (IS_ERR(fp_mac)) {
537                 DHD_ERROR(("[WIFI_SEC] %s: File open error\n", filepath_efs));
538                 return -1;
539         }       else {
540                 oldfs = get_fs();
541                 set_fs(get_ds());
542
543                 if (fp_mac->f_mode & FMODE_WRITE) {
544                         ret = fp_mac->f_op->write(fp_mac, (const char *)buf,
545                                 sizeof(buf), &fp_mac->f_pos);
546                         if (ret < 0)
547                                 DHD_ERROR(("[WIFI_SEC] Mac address [%s] Failed"
548                                 " to write into File: %s\n", buf, filepath_efs));
549                         else
550                                 DHD_INFO(("[WIFI_SEC] Mac address [%s] written"
551                                 " into File: %s\n", buf, filepath_efs));
552                 }
553                 set_fs(oldfs);
554                 filp_close(fp_mac, NULL);
555         }
556
557         return 0;
558
559 }
560
561 int dhd_check_rdwr_macaddr(struct dhd_info *dhd, dhd_pub_t *dhdp,
562         struct ether_addr *mac)
563 {
564         struct file *fp_mac = NULL;
565         struct file *fp_nvm = NULL;
566         char macbuffer[18]    = {0};
567         char randommac[3]   = {0};
568         char buf[18]      = {0};
569         char *filepath_data      = MACINFO;
570         char *filepath_efs      = MACINFO_EFS;
571 #ifdef CONFIG_TARGET_LOCALE_NA
572         char *nvfilepath       = "/data/misc/wifi/.nvmac.info";
573 #else
574         char *nvfilepath = "/efs/wifi/.nvmac.info";
575 #endif
576         char cur_mac[128]   = {0};
577         char dummy_mac[ETHER_ADDR_LEN] = {0x00, 0x90, 0x4C, 0xC5, 0x12, 0x38};
578         char cur_macbuffer[18]  = {0};
579         int ret = -1;
580
581         g_imac_flag = MACADDR_NONE;
582
583         fp_nvm = filp_open(nvfilepath, O_RDONLY, 0);
584         if (IS_ERR(fp_nvm)) { /* file does not exist */
585
586                 /* read MAC Address */
587                 strcpy(cur_mac, "cur_etheraddr");
588                 ret = dhd_wl_ioctl_cmd(dhdp, WLC_GET_VAR, cur_mac,
589                         sizeof(cur_mac), 0, 0);
590                 if (ret < 0) {
591                         DHD_ERROR(("[WIFI_SEC] Current READ MAC error \r\n"));
592                         memset(cur_mac, 0, ETHER_ADDR_LEN);
593                         return -1;
594                 } else {
595                         DHD_ERROR(("[WIFI_SEC] MAC (OTP) : "
596                         "[%02X:%02X:%02X:%02X:%02X:%02X] \r\n",
597                         cur_mac[0], cur_mac[1], cur_mac[2], cur_mac[3],
598                         cur_mac[4], cur_mac[5]));
599                 }
600
601                 sprintf(cur_macbuffer, "%02X:%02X:%02X:%02X:%02X:%02X\n",
602                         cur_mac[0], cur_mac[1], cur_mac[2],
603                         cur_mac[3], cur_mac[4], cur_mac[5]);
604
605                 fp_mac = filp_open(filepath_data, O_RDONLY, 0);
606                 if (IS_ERR(fp_mac)) { /* file does not exist */
607                         /* read mac is the dummy mac (00:90:4C:C5:12:38) */
608                         if (memcmp(cur_mac, dummy_mac, ETHER_ADDR_LEN) == 0)
609                                 g_imac_flag = MACADDR_MOD_RANDOM;
610                         else if (strncmp(buf, "00:00:00:00:00:00", 17) == 0)
611                                 g_imac_flag = MACADDR_MOD_RANDOM;
612                         else
613                                 g_imac_flag = MACADDR_MOD;
614                 } else {
615                         int is_zeromac;
616
617                         ret = kernel_read(fp_mac, 0, buf, 18);
618                         filp_close(fp_mac, NULL);
619                         buf[17] = '\0';
620
621                         is_zeromac = strncmp(buf, "00:00:00:00:00:00", 17);
622                         DHD_ERROR(("[WIFI_SEC] MAC (FILE): [%s] [%d] \r\n",
623                                 buf, is_zeromac));
624
625                         if (is_zeromac == 0) {
626                                 DHD_ERROR(("[WIFI_SEC] Zero MAC detected."
627                                         " Trying Random MAC.\n"));
628                                 g_imac_flag = MACADDR_MOD_RANDOM;
629                         } else {
630                                 sscanf(buf, "%02X:%02X:%02X:%02X:%02X:%02X",
631                                         (unsigned int *)&(mac->octet[0]),
632                                         (unsigned int *)&(mac->octet[1]),
633                                         (unsigned int *)&(mac->octet[2]),
634                                         (unsigned int *)&(mac->octet[3]),
635                                         (unsigned int *)&(mac->octet[4]),
636                                         (unsigned int *)&(mac->octet[5]));
637                         /* current MAC address is same as previous one */
638                                 if (memcmp(cur_mac, mac->octet, ETHER_ADDR_LEN) == 0) {
639                                         g_imac_flag = MACADDR_NONE;
640                                 } else { /* change MAC address */
641                                         if (_dhd_set_mac_address(dhd, 0, mac) == 0) {
642                                                 DHD_INFO(("[WIFI_SEC] %s: MACID is"
643                                                 " overwritten\n", __FUNCTION__));
644                                                 g_imac_flag = MACADDR_MOD;
645                                         } else {
646                                                 DHD_ERROR(("[WIFI_SEC] %s: "
647                                                 "_dhd_set_mac_address()"
648                                                 " failed\n", __FUNCTION__));
649                                                 g_imac_flag = MACADDR_NONE;
650                                         }
651                                 }
652                         }
653                 }
654                 fp_mac = filp_open(filepath_efs, O_RDONLY, 0);
655                 if (IS_ERR(fp_mac)) { /* file does not exist */
656                         /* read mac is the dummy mac (00:90:4C:C5:12:38) */
657                         if (memcmp(cur_mac, dummy_mac, ETHER_ADDR_LEN) == 0)
658                                 g_imac_flag = MACADDR_MOD_RANDOM;
659                         else if (strncmp(buf, "00:00:00:00:00:00", 17) == 0)
660                                 g_imac_flag = MACADDR_MOD_RANDOM;
661                         else
662                                 g_imac_flag = MACADDR_MOD;
663                 } else {
664                         int is_zeromac;
665
666                         ret = kernel_read(fp_mac, 0, buf, 18);
667                         filp_close(fp_mac, NULL);
668                         buf[17] = '\0';
669
670                         is_zeromac = strncmp(buf, "00:00:00:00:00:00", 17);
671                         DHD_ERROR(("[WIFI_SEC] MAC (FILE): [%s] [%d] \r\n",
672                                 buf, is_zeromac));
673
674                         if (is_zeromac == 0) {
675                                 DHD_ERROR(("[WIFI_SEC] Zero MAC detected."
676                                         " Trying Random MAC.\n"));
677                                 g_imac_flag = MACADDR_MOD_RANDOM;
678                         } else {
679                                 sscanf(buf, "%02X:%02X:%02X:%02X:%02X:%02X",
680                                         (unsigned int *)&(mac->octet[0]),
681                                         (unsigned int *)&(mac->octet[1]),
682                                         (unsigned int *)&(mac->octet[2]),
683                                         (unsigned int *)&(mac->octet[3]),
684                                         (unsigned int *)&(mac->octet[4]),
685                                         (unsigned int *)&(mac->octet[5]));
686                         /* current MAC address is same as previous one */
687                                 if (memcmp(cur_mac, mac->octet, ETHER_ADDR_LEN) == 0) {
688                                         g_imac_flag = MACADDR_NONE;
689                                 } else { /* change MAC address */
690                                         if (_dhd_set_mac_address(dhd, 0, mac) == 0) {
691                                                 DHD_INFO(("[WIFI_SEC] %s: MACID is"
692                                                 " overwritten\n", __FUNCTION__));
693                                                 g_imac_flag = MACADDR_MOD;
694                                         } else {
695                                                 DHD_ERROR(("[WIFI_SEC] %s: "
696                                                 "_dhd_set_mac_address()"
697                                                 " failed\n", __FUNCTION__));
698                                                 g_imac_flag = MACADDR_NONE;
699                                         }
700                                 }
701                         }
702                 }
703         } else {
704                 /* COB type. only COB. */
705                 /* Reading the MAC Address from .nvmac.info file
706                  * (the existed file or just created file)
707                  */
708                 ret = kernel_read(fp_nvm, 0, buf, 18);
709
710                 /* to prevent abnormal string display when mac address
711                  * is displayed on the screen.
712                  */
713                 buf[17] = '\0';
714                 DHD_ERROR(("[WIFI_SEC] Read MAC : [%s] [%d] \r\n", buf,
715                         strncmp(buf, "00:00:00:00:00:00", 17)));
716                 if ((buf[0] == '\0') ||
717                         (strncmp(buf, "00:00:00:00:00:00", 17) == 0)) {
718                         g_imac_flag = MACADDR_COB_RANDOM;
719                 } else {
720                         sscanf(buf, "%02X:%02X:%02X:%02X:%02X:%02X",
721                                 (unsigned int *)&(mac->octet[0]),
722                                 (unsigned int *)&(mac->octet[1]),
723                                 (unsigned int *)&(mac->octet[2]),
724                                 (unsigned int *)&(mac->octet[3]),
725                                 (unsigned int *)&(mac->octet[4]),
726                                 (unsigned int *)&(mac->octet[5]));
727                         /* Writing Newly generated MAC ID to the Dongle */
728                         if (_dhd_set_mac_address(dhd, 0, mac) == 0) {
729                                 DHD_INFO(("[WIFI_SEC] %s: MACID is overwritten\n",
730                                         __FUNCTION__));
731                                 g_imac_flag = MACADDR_COB;
732                         } else {
733                                 DHD_ERROR(("[WIFI_SEC] %s: _dhd_set_mac_address()"
734                                         " failed\n", __FUNCTION__));
735                         }
736                 }
737                 filp_close(fp_nvm, NULL);
738         }
739
740         if ((g_imac_flag == MACADDR_COB_RANDOM) ||
741             (g_imac_flag == MACADDR_MOD_RANDOM)) {
742                 get_random_bytes(randommac, 3);
743                 sprintf(macbuffer, "%02X:%02X:%02X:%02X:%02X:%02X\n",
744                         0x60, 0xd0, 0xa9, randommac[0], randommac[1],
745                         randommac[2]);
746                 DHD_ERROR(("[WIFI_SEC] The Random Generated MAC ID : %s\n",
747                         macbuffer));
748                 sscanf(macbuffer, "%02X:%02X:%02X:%02X:%02X:%02X",
749                         (unsigned int *)&(mac->octet[0]),
750                         (unsigned int *)&(mac->octet[1]),
751                         (unsigned int *)&(mac->octet[2]),
752                         (unsigned int *)&(mac->octet[3]),
753                         (unsigned int *)&(mac->octet[4]),
754                         (unsigned int *)&(mac->octet[5]));
755                 if (_dhd_set_mac_address(dhd, 0, mac) == 0) {
756                         DHD_INFO(("[WIFI_SEC] %s: MACID is overwritten\n", __FUNCTION__));
757                         g_imac_flag = MACADDR_COB;
758                 } else {
759                         DHD_ERROR(("[WIFI_SEC] %s: _dhd_set_mac_address() failed\n",
760                                 __FUNCTION__));
761                 }
762         }
763
764         return 0;
765 }
766 #endif /* RDWR_MACADDR */
767
768 #ifdef RDWR_KORICS_MACADDR
769 int dhd_write_rdwr_korics_macaddr(struct dhd_info *dhd, struct ether_addr *mac)
770 {
771         struct file *fp      = NULL;
772         char macbuffer[18]   = {0};
773         mm_segment_t oldfs   = {0};
774         char randommac[3]    = {0};
775         char buf[18]         = {0};
776         char *filepath_efs       = MACINFO_EFS;
777         int is_zeromac       = 0;
778         int ret = 0;
779         /* MAC address copied from efs/wifi.mac.info */
780         fp = filp_open(filepath_efs, O_RDONLY, 0);
781
782         if (IS_ERR(fp)) {
783                 /* File Doesn't Exist. Create and write mac addr. */
784                 fp = filp_open(filepath_efs, O_RDWR | O_CREAT, 0666);
785                 if (IS_ERR(fp)) {
786                         DHD_ERROR(("[WIFI_SEC] %s: File open error\n",
787                                 filepath_efs));
788                         return -1;
789                 }
790
791                 oldfs = get_fs();
792                 set_fs(get_ds());
793
794                 /* Generating the Random Bytes for
795                  * 3 last octects of the MAC address
796                  */
797                 get_random_bytes(randommac, 3);
798
799                 sprintf(macbuffer, "%02X:%02X:%02X:%02X:%02X:%02X\n",
800                         0x60, 0xd0, 0xa9, randommac[0],
801                         randommac[1], randommac[2]);
802                 DHD_ERROR(("[WIFI_SEC] The Random Generated MAC ID : %s\n",
803                         macbuffer));
804
805                 if (fp->f_mode & FMODE_WRITE) {
806                         ret = fp->f_op->write(fp,
807                                 (const char *)macbuffer,
808                                 sizeof(macbuffer), &fp->f_pos);
809                         if (ret < 0)
810                                 DHD_ERROR(("[WIFI_SEC] Mac address [%s]"
811                                         " Failed to write into File:"
812                                         " %s\n", macbuffer, filepath_efs));
813                         else
814                                 DHD_ERROR(("[WIFI_SEC] Mac address [%s]"
815                                         " written into File: %s\n",
816                                         macbuffer, filepath_efs));
817                 }
818                 set_fs(oldfs);
819         } else {
820         /* Reading the MAC Address from .mac.info file
821          * (the existed file or just created file)
822          */
823             ret = kernel_read(fp, 0, buf, 18);
824                 /* to prevent abnormal string display when mac address
825                  * is displayed on the screen.
826                  */
827                 buf[17] = '\0';
828                 /* Remove security log */
829                 /* DHD_ERROR(("Read MAC : [%s] [%d] \r\n", buf,
830                  * strncmp(buf, "00:00:00:00:00:00", 17)));
831                  */
832                 if ((buf[0] == '\0') ||
833                         (strncmp(buf, "00:00:00:00:00:00", 17) == 0)) {
834                         is_zeromac = 1;
835                 }
836         }
837
838         if (ret)
839                 sscanf(buf, "%02X:%02X:%02X:%02X:%02X:%02X",
840                         (unsigned int *)&(mac->octet[0]),
841                         (unsigned int *)&(mac->octet[1]),
842                         (unsigned int *)&(mac->octet[2]),
843                         (unsigned int *)&(mac->octet[3]),
844                         (unsigned int *)&(mac->octet[4]),
845                         (unsigned int *)&(mac->octet[5]));
846         else
847                 DHD_INFO(("[WIFI_SEC] dhd_bus_start: Reading from the"
848                         " '%s' returns 0 bytes\n", filepath_efs));
849
850         if (fp)
851                 filp_close(fp, NULL);
852
853         if (!is_zeromac) {
854                 /* Writing Newly generated MAC ID to the Dongle */
855                 if (_dhd_set_mac_address(dhd, 0, mac) == 0)
856                         DHD_INFO(("[WIFI_SEC] dhd_bus_start: MACID is overwritten\n"));
857                 else
858                         DHD_ERROR(("[WIFI_SEC] dhd_bus_start: _dhd_set_mac_address() "
859                                 "failed\n"));
860         } else {
861                 DHD_ERROR(("[WIFI_SEC] dhd_bus_start:Is ZeroMAC BypassWrite.mac.info!\n"));
862         }
863
864         return 0;
865 }
866 #endif /* RDWR_KORICS_MACADDR */
867
868 #ifdef USE_CID_CHECK
869 static int dhd_write_cid_file(const char *filepath_cid, const char *buf, int buf_len)
870 {
871         struct file *fp = NULL;
872         mm_segment_t oldfs = {0};
873         int ret = 0;
874
875         /* File is always created. */
876         fp = filp_open(filepath_cid, O_RDWR | O_CREAT, 0666);
877         if (IS_ERR(fp)) {
878                 DHD_ERROR(("[WIFI_SEC] %s: File open error\n", filepath_cid));
879                 return -1;
880         } else {
881                 oldfs = get_fs();
882                 set_fs(get_ds());
883
884                 if (fp->f_mode & FMODE_WRITE) {
885                         ret = fp->f_op->write(fp, buf, buf_len, &fp->f_pos);
886                         if (ret < 0)
887                                 DHD_ERROR(("[WIFI_SEC] Failed to write CIS[%s]"
888                                         " into '%s'\n", buf, filepath_cid));
889                         else
890                                 DHD_ERROR(("[WIFI_SEC] CID [%s] written into"
891                                         " '%s'\n", buf, filepath_cid));
892                 }
893                 set_fs(oldfs);
894         }
895         filp_close(fp, NULL);
896
897         return 0;
898 }
899
900 #ifdef DUMP_CIS
901 static void dhd_dump_cis(const unsigned char *buf, int size)
902 {
903         int i;
904         for (i = 0; i < size; i++) {
905                 DHD_ERROR(("%02X ", buf[i]));
906                 if ((i % 15) == 15) DHD_ERROR(("\n"));
907         }
908         DHD_ERROR(("\n"));
909 }
910 #endif /* DUMP_CIS */
911
912 #define MAX_VID_LEN             8
913 #define MAX_VNAME_LEN           16
914
915 typedef struct {
916         uint8 vid_length;
917         unsigned char vid[MAX_VID_LEN];
918         char vname[MAX_VNAME_LEN];
919 } vid_info_t;
920
921 #if defined(BCM4330_CHIP)
922 vid_info_t vid_info[] = {
923         { 6, { 0x00, 0x20, 0xc7, 0x00, 0x00, }, { "murata" } },
924         { 2, { 0x99, }, { "semcove" } },
925         { 0, { 0x00, }, { "samsung" } }
926 };
927 #elif defined(BCM43430_CHIP)
928 vid_info_t vid_info[] = {
929         { 3, { 0x33, 0x33, }, { "semco" } },
930         { 3, { 0x00, 0x22, }, { "murata" } },
931         { 0, { 0x00, }, { "samsung" } }
932 };
933 #elif defined(BCM4334_CHIP)
934 vid_info_t vid_info[] = {
935         { 6, { 0x00, 0x00, 0x00, 0x33, 0x33, }, { "semco" } },
936         { 6, { 0x00, 0x00, 0x00, 0xfb, 0x50, }, { "semcosh" } },
937         { 6, { 0x00, 0x20, 0xc7, 0x00, 0x00, }, { "murata" } },
938         { 0, { 0x00, }, { "murata" } }
939 };
940 #elif defined(BCM4335_CHIP)
941 vid_info_t vid_info[] = {
942         { 3, { 0x33, 0x66, }, { "semcosh" } },          /* B0 Sharp 5G-FEM */
943         { 3, { 0x33, 0x33, }, { "semco" } },            /* B0 Skyworks 5G-FEM and A0 chip */
944         { 3, { 0x33, 0x88, }, { "semco3rd" } },         /* B0 Syri 5G-FEM */
945         { 3, { 0x00, 0x11, }, { "muratafem1" } },       /* B0 ANADIGICS 5G-FEM */
946         { 3, { 0x00, 0x22, }, { "muratafem2" } },       /* B0 TriQuint 5G-FEM */
947         { 3, { 0x00, 0x33, }, { "muratafem3" } },       /* 3rd FEM: Reserved */
948         { 0, { 0x00, }, { "murata" } }  /* Default: for Murata A0 module */
949 };
950 #elif defined(BCM4339_CHIP) || defined(BCM4354_CHIP)
951 vid_info_t vid_info[] = {                         /* 4339:2G FEM+5G FEM ,4354: 2G FEM+5G FEM */
952         { 3, { 0x33, 0x33, }, { "semco" } },      /* 4339:Skyworks+sharp,4354:Panasonic+Panasonic */
953         { 3, { 0x33, 0x66, }, { "semco" } },      /* 4339:  , 4354:Panasonic+SEMCO */
954         { 3, { 0x33, 0x88, }, { "semco3rd" } },   /* 4339:  , 4354:SEMCO+SEMCO */
955         { 3, { 0x90, 0x01, }, { "wisol" } },      /* 4339:  , 4354:Microsemi+Panasonic */
956         { 3, { 0x90, 0x02, }, { "wisolfem1" } },  /* 4339:  , 4354:Panasonic+Panasonic */
957         { 3, { 0x90, 0x03, }, { "wisolfem2" } },  /* 4354:Murata+Panasonic */
958         { 3, { 0x00, 0x11, }, { "muratafem1" } }, /* 4339:  , 4354:Murata+Anadigics */
959         { 3, { 0x00, 0x22, }, { "muratafem2"} },  /* 4339:  , 4354:Murata+Triquint */
960         { 0, { 0x00, }, { "samsung" } }           /* Default: Not specified yet */
961 };
962 #else
963 vid_info_t vid_info[] = {
964         { 0, { 0x00, }, { "samsung" } }                 /* Default: Not specified yet */
965 };
966 #endif /* BCM_CHIP_ID */
967
968 int dhd_check_module_cid(dhd_pub_t *dhd)
969 {
970         int ret = -1;
971         unsigned char cis_buf[CIS_BUF_SIZE] = {0};
972         const char *cidfilepath = CIDINFO;
973         cis_rw_t *cish = (cis_rw_t *)&cis_buf[8];
974         int idx, max;
975         vid_info_t *cur_info;
976         unsigned char *vid_start;
977         unsigned char vid_length;
978 #if defined(BCM4334_CHIP) || defined(BCM4335_CHIP)
979         const char *revfilepath = REVINFO;
980 #ifdef BCM4334_CHIP
981         int flag_b3;
982 #else
983         char rev_str[10] = {0};
984 #endif /* BCM4334_CHIP */
985 #endif /* BCM4334_CHIP || BCM4335_CHIP */
986
987         /* Try reading out from CIS */
988         cish->source = 0;
989         cish->byteoff = 0;
990         cish->nbytes = sizeof(cis_buf);
991
992         strcpy(cis_buf, "cisdump");
993         ret = dhd_wl_ioctl_cmd(dhd, WLC_GET_VAR, cis_buf,
994                 sizeof(cis_buf), 0, 0);
995         if (ret < 0) {
996                 DHD_ERROR(("[WIFI_SEC] %s: CIS reading failed, ret=%d\n",
997                         __FUNCTION__, ret));
998                 return ret;
999         }
1000
1001         DHD_ERROR(("[WIFI_SEC] %s: CIS reading success, ret=%d\n",
1002                 __FUNCTION__, ret));
1003 #ifdef DUMP_CIS
1004         dhd_dump_cis(cis_buf, 48);
1005 #endif
1006
1007         max = sizeof(cis_buf) - 4;
1008         for (idx = 0; idx < max; idx++) {
1009                 if (cis_buf[idx] == CIS_TUPLE_TAG_START) {
1010                         if (cis_buf[idx + 2] == CIS_TUPLE_TAG_VENDOR) {
1011                                 vid_length = cis_buf[idx + 1];
1012                                 vid_start = &cis_buf[idx + 3];
1013                                 /* found CIS tuple */
1014                                 break;
1015                         } else {
1016                                 /* Go to next tuple if tuple value is not vendor type */
1017                                 idx += (cis_buf[idx + 1] + 1);
1018                         }
1019                 }
1020         }
1021
1022         if (idx < max) {
1023                 max = sizeof(vid_info) / sizeof(vid_info_t);
1024                 for (idx = 0; idx < max; idx++) {
1025                         cur_info = &vid_info[idx];
1026                         if ((cur_info->vid_length == vid_length) &&
1027                                 (cur_info->vid_length != 0) &&
1028                                 (memcmp(cur_info->vid, vid_start, cur_info->vid_length - 1) == 0))
1029                                 goto write_cid;
1030                 }
1031         }
1032
1033         /* find default nvram, if exist */
1034         DHD_ERROR(("[WIFI_SEC] %s: cannot find CIS TUPLE set as default\n", __FUNCTION__));
1035         max = sizeof(vid_info) / sizeof(vid_info_t);
1036         for (idx = 0; idx < max; idx++) {
1037                 cur_info = &vid_info[idx];
1038                 if (cur_info->vid_length == 0)
1039                         goto write_cid;
1040         }
1041         DHD_ERROR(("[WIFI_SEC] %s: cannot find default CID\n", __FUNCTION__));
1042         return -1;
1043
1044 write_cid:
1045         DHD_ERROR(("[WIFI_SEC] CIS MATCH FOUND : %s\n", cur_info->vname));
1046         dhd_write_cid_file(cidfilepath, cur_info->vname, strlen(cur_info->vname)+1);
1047 #if defined(BCM4334_CHIP)
1048         /* Try reading out from OTP to distinguish B2 or B3 */
1049         memset(cis_buf, 0, sizeof(cis_buf));
1050         cish = (cis_rw_t *)&cis_buf[8];
1051
1052         cish->source = 0;
1053         cish->byteoff = 0;
1054         cish->nbytes = sizeof(cis_buf);
1055
1056         strcpy(cis_buf, "otpdump");
1057         ret = dhd_wl_ioctl_cmd(dhd, WLC_GET_VAR, cis_buf,
1058                 sizeof(cis_buf), 0, 0);
1059         if (ret < 0) {
1060                 DHD_ERROR(("[WIFI_SEC] %s: OTP reading failed, err=%d\n",
1061                         __FUNCTION__, ret));
1062                 return ret;
1063         }
1064
1065         /* otp 33th character is identifier for 4334B3 */
1066         cis_buf[34] = '\0';
1067         flag_b3 = bcm_atoi(&cis_buf[33]);
1068         if (flag_b3 & 0x1) {
1069                 DHD_ERROR(("[WIFI_SEC] REV MATCH FOUND : 4334B3, %c\n", cis_buf[33]));
1070                 dhd_write_cid_file(revfilepath, "4334B3", 6);
1071         }
1072 #endif /* BCM4334_CHIP */
1073 #if defined(BCM4335_CHIP)
1074         DHD_TRACE(("[WIFI_SEC] %s: BCM4335 Multiple Revision Check\n", __FUNCTION__));
1075         if (concate_revision(dhd->bus, rev_str, sizeof(rev_str),
1076                 rev_str, sizeof(rev_str)) < 0) {
1077                 DHD_ERROR(("[WIFI_SEC] %s: fail to concate revision\n", __FUNCTION__));
1078                 ret = -1;
1079         } else {
1080                 if (strstr(rev_str, "_a0")) {
1081                         DHD_ERROR(("[WIFI_SEC] REV MATCH FOUND : 4335A0\n"));
1082                         dhd_write_cid_file(revfilepath, "BCM4335A0", 9);
1083                 } else {
1084                         DHD_ERROR(("[WIFI_SEC] REV MATCH FOUND : 4335B0\n"));
1085                         dhd_write_cid_file(revfilepath, "BCM4335B0", 9);
1086                 }
1087         }
1088 #endif /* BCM4335_CHIP */
1089
1090         return ret;
1091 }
1092 #endif /* USE_CID_CHECK */
1093
1094 #ifdef GET_MAC_FROM_OTP
1095 static int dhd_write_mac_file(const char *filepath, const char *buf, int buf_len)
1096 {
1097         struct file *fp = NULL;
1098         mm_segment_t oldfs = {0};
1099         int ret = 0;
1100
1101         fp = filp_open(filepath, O_RDWR | O_CREAT, 0666);
1102         /* File is always created. */
1103         if (IS_ERR(fp)) {
1104                 DHD_ERROR(("[WIFI_SEC] File open error\n"));
1105                 return -1;
1106         } else {
1107                 oldfs = get_fs();
1108                 set_fs(get_ds());
1109
1110                 if (fp->f_mode & FMODE_WRITE) {
1111                         ret = fp->f_op->write(fp, buf, buf_len, &fp->f_pos);
1112                         if (ret < 0)
1113                                 DHD_ERROR(("[WIFI_SEC] Failed to write CIS. \n"));
1114                         else
1115                                 DHD_ERROR(("[WIFI_SEC] MAC written. \n"));
1116                 }
1117                 set_fs(oldfs);
1118         }
1119         filp_close(fp, NULL);
1120
1121         return 0;
1122 }
1123
1124 int dhd_check_module_mac(dhd_pub_t *dhd, struct ether_addr *mac)
1125 {
1126         int ret = -1;
1127         unsigned char cis_buf[CIS_BUF_SIZE] = {0};
1128         unsigned char mac_buf[20] = {0};
1129         unsigned char otp_mac_buf[20] = {0};
1130         const char *macfilepath = MACINFO_EFS;
1131
1132         /* Try reading out from CIS */
1133         cis_rw_t *cish = (cis_rw_t *)&cis_buf[8];
1134         struct file *fp_mac = NULL;
1135
1136         cish->source = 0;
1137         cish->byteoff = 0;
1138         cish->nbytes = sizeof(cis_buf);
1139
1140         strcpy(cis_buf, "cisdump");
1141         ret = dhd_wl_ioctl_cmd(dhd, WLC_GET_VAR, cis_buf,
1142                 sizeof(cis_buf), 0, 0);
1143         if (ret < 0) {
1144                 DHD_TRACE(("[WIFI_SEC] %s: CIS reading failed, ret=%d\n", __func__,
1145                         ret));
1146                 sprintf(otp_mac_buf, "%02X:%02X:%02X:%02X:%02X:%02X\n",
1147                         mac->octet[0], mac->octet[1], mac->octet[2],
1148                         mac->octet[3], mac->octet[4], mac->octet[5]);
1149                 DHD_ERROR(("[WIFI_SEC] %s: Check module mac by legacy FW : " MACDBG "\n",
1150                         __FUNCTION__, MAC2STRDBG(mac->octet)));
1151         } else {
1152                 bcm_tlv_t *elt = NULL;
1153                 int remained_len = sizeof(cis_buf);
1154                 int index = 0;
1155                 uint8 *mac_addr = NULL;
1156 #ifdef DUMP_CIS
1157                 dhd_dump_cis(cis_buf, 48);
1158 #endif
1159
1160                 /* Find a new tuple tag */
1161                 while (index < remained_len) {
1162                         if (cis_buf[index] == CIS_TUPLE_TAG_START) {
1163                                 remained_len -= index;
1164                                 if (remained_len >= sizeof(bcm_tlv_t)) {
1165                                         elt = (bcm_tlv_t *)&cis_buf[index];
1166                                 }
1167                                 break;
1168                         } else {
1169                                 index++;
1170                         }
1171
1172                 }
1173
1174                 /* Find a MAC address tuple */
1175                 while (elt && remained_len >= TLV_HDR_LEN) {
1176                         int body_len = (int)elt->len;
1177
1178                         if ((elt->id == CIS_TUPLE_TAG_START) &&
1179                                 (remained_len >= (body_len + TLV_HDR_LEN)) &&
1180                                 (*elt->data == CIS_TUPLE_TAG_MACADDR)) {
1181                                 /* found MAC Address tuple and
1182                                  * get the MAC Address data
1183                                  */
1184                                 mac_addr = (uint8 *)elt + CIS_TUPLE_TAG_MACADDR_OFF;
1185                                 break;
1186                         }
1187
1188                         /* Go to next tuple if tuple value
1189                          * is not MAC address type
1190                          */
1191                         elt = (bcm_tlv_t *)((uint8 *)elt + (body_len + TLV_HDR_LEN));
1192                         remained_len -= (body_len + TLV_HDR_LEN);
1193                 }
1194
1195                 if (mac_addr) {
1196                         sprintf(otp_mac_buf, "%02X:%02X:%02X:%02X:%02X:%02X\n",
1197                                 mac_addr[0], mac_addr[1], mac_addr[2],
1198                                 mac_addr[3], mac_addr[4], mac_addr[5]);
1199                         DHD_ERROR(("[WIFI_SEC] MAC address is taken from OTP\n"));
1200                 } else {
1201                         sprintf(otp_mac_buf, "%02X:%02X:%02X:%02X:%02X:%02X\n",
1202                                 mac->octet[0], mac->octet[1], mac->octet[2],
1203                                 mac->octet[3], mac->octet[4], mac->octet[5]);
1204                         DHD_ERROR(("[WIFI_SEC] %s: Cannot find MAC address info from OTP,"
1205                                 " Check module mac by initial value: " MACDBG "\n",
1206                                 __FUNCTION__, MAC2STRDBG(mac->octet)));
1207                 }
1208         }
1209
1210         fp_mac = filp_open(macfilepath, O_RDONLY, 0);
1211         if (!IS_ERR(fp_mac)) {
1212                 DHD_ERROR(("[WIFI_SEC] Check Mac address in .mac.info \n"));
1213                 kernel_read(fp_mac, fp_mac->f_pos, mac_buf, sizeof(mac_buf));
1214                 filp_close(fp_mac, NULL);
1215
1216                 if (strncmp(mac_buf, otp_mac_buf, 17) != 0) {
1217                         DHD_ERROR(("[WIFI_SEC] file MAC is wrong. Write OTP MAC in .mac.info \n"));
1218                         dhd_write_mac_file(macfilepath, otp_mac_buf, sizeof(otp_mac_buf));
1219                 }
1220         }
1221
1222         return ret;
1223 }
1224 #endif /* GET_MAC_FROM_OTP */
1225
1226 #ifdef WRITE_MACADDR
1227 int dhd_write_macaddr(struct ether_addr *mac)
1228 {
1229         char *filepath_data      = MACINFO;
1230         char *filepath_efs      = MACINFO_EFS;
1231
1232         struct file *fp_mac = NULL;
1233         char buf[WRMAC_BUF_SIZE]      = {0};
1234         mm_segment_t oldfs    = {0};
1235         int ret = -1;
1236         int retry_count = 0;
1237
1238 startwrite:
1239
1240         sprintf(buf, "%02X:%02X:%02X:%02X:%02X:%02X\n",
1241                 mac->octet[0], mac->octet[1], mac->octet[2],
1242                 mac->octet[3], mac->octet[4], mac->octet[5]);
1243
1244         /* File will be created /data/.mac.info. */
1245         fp_mac = filp_open(filepath_data, O_RDWR | O_CREAT, 0666);
1246
1247         if (IS_ERR(fp_mac)) {
1248                 DHD_ERROR(("[WIFI_SEC] %s: File open error\n", filepath_data));
1249                 return -1;
1250         } else {
1251                 oldfs = get_fs();
1252                 set_fs(get_ds());
1253
1254                 if (fp_mac->f_mode & FMODE_WRITE) {
1255                         ret = fp_mac->f_op->write(fp_mac, (const char *)buf,
1256                                 sizeof(buf), &fp_mac->f_pos);
1257                         if (ret < 0)
1258                                 DHD_ERROR(("[WIFI_SEC] Mac address [%s] Failed to"
1259                                 " write into File: %s\n", buf, filepath_data));
1260                         else
1261                                 DHD_INFO(("[WIFI_SEC] Mac address [%s] written"
1262                                 " into File: %s\n", buf, filepath_data));
1263                 }
1264                 set_fs(oldfs);
1265                 filp_close(fp_mac, NULL);
1266         }
1267         /* check .mac.info file is 0 byte */
1268         fp_mac = filp_open(filepath_data, O_RDONLY, 0);
1269         ret = kernel_read(fp_mac, 0, buf, 18);
1270
1271         if ((ret == 0) && (retry_count++ < 3)) {
1272                 filp_close(fp_mac, NULL);
1273                 goto startwrite;
1274         }
1275
1276         filp_close(fp_mac, NULL);
1277         /* end of /data/.mac.info */
1278
1279         if (filepath_efs == NULL) {
1280                 DHD_ERROR(("[WIFI_SEC] %s : no efs filepath", __func__));
1281                 return 0;
1282         }
1283
1284         /* File will be created /efs/wifi/.mac.info. */
1285         fp_mac = filp_open(filepath_efs, O_RDWR | O_CREAT, 0666);
1286
1287         if (IS_ERR(fp_mac)) {
1288                 DHD_ERROR(("[WIFI_SEC] %s: File open error\n", filepath_efs));
1289                 return -1;
1290         } else {
1291                 oldfs = get_fs();
1292                 set_fs(get_ds());
1293
1294                 if (fp_mac->f_mode & FMODE_WRITE) {
1295                         ret = fp_mac->f_op->write(fp_mac, (const char *)buf,
1296                                 sizeof(buf), &fp_mac->f_pos);
1297                         if (ret < 0)
1298                                 DHD_ERROR(("[WIFI_SEC] Mac address [%s] Failed to"
1299                                 " write into File: %s\n", buf, filepath_efs));
1300                         else
1301                                 DHD_INFO(("[WIFI_SEC] Mac address [%s] written"
1302                                 " into File: %s\n", buf, filepath_efs));
1303                 }
1304                 set_fs(oldfs);
1305                 filp_close(fp_mac, NULL);
1306         }
1307
1308         /* check .mac.info file is 0 byte */
1309         fp_mac = filp_open(filepath_efs, O_RDONLY, 0);
1310         ret = kernel_read(fp_mac, 0, buf, 18);
1311
1312         if ((ret == 0) && (retry_count++ < 3)) {
1313                 filp_close(fp_mac, NULL);
1314                 goto startwrite;
1315         }
1316
1317         filp_close(fp_mac, NULL);
1318
1319         return 0;
1320 }
1321 #endif /* WRITE_MACADDR */
1322
1323 #ifdef CONFIG_CONTROL_PM
1324 extern bool g_pm_control;
1325 void sec_control_pm(dhd_pub_t *dhd, uint *power_mode)
1326 {
1327         struct file *fp = NULL;
1328         char *filepath = PSMINFO;
1329         char power_val = 0;
1330         char iovbuf[WL_EVENTING_MASK_LEN + 12];
1331 #ifdef DHD_ENABLE_LPC
1332         int ret = 0;
1333         uint32 lpc = 0;
1334 #endif /* DHD_ENABLE_LPC */
1335
1336         g_pm_control = FALSE;
1337
1338         fp = filp_open(filepath, O_RDONLY, 0);
1339         if (IS_ERR(fp) || (fp == NULL)) {
1340                 /* Enable PowerSave Mode */
1341                 dhd_wl_ioctl_cmd(dhd, WLC_SET_PM, (char *)power_mode,
1342                         sizeof(uint), TRUE, 0);
1343                 DHD_ERROR(("[WIFI_SEC] %s: /data/.psm.info open failed,"
1344                         " so set PM to %d\n",
1345                         __FUNCTION__, *power_mode));
1346                 return;
1347         } else {
1348                 kernel_read(fp, fp->f_pos, &power_val, 1);
1349                 DHD_ERROR(("[WIFI_SEC] %s: POWER_VAL = %c \r\n", __FUNCTION__, power_val));
1350
1351                 if (power_val == '0') {
1352 #ifdef ROAM_ENABLE
1353                         uint roamvar = 1;
1354 #endif
1355                         *power_mode = PM_OFF;
1356                         /* Disable PowerSave Mode */
1357                         dhd_wl_ioctl_cmd(dhd, WLC_SET_PM, (char *)power_mode,
1358                                 sizeof(uint), TRUE, 0);
1359                         /* Turn off MPC in AP mode */
1360                         bcm_mkiovar("mpc", (char *)power_mode, 4,
1361                                 iovbuf, sizeof(iovbuf));
1362                         dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf,
1363                                 sizeof(iovbuf), TRUE, 0);
1364                         g_pm_control = TRUE;
1365 #ifdef ROAM_ENABLE
1366                         /* Roaming off of dongle */
1367                         bcm_mkiovar("roam_off", (char *)&roamvar, 4,
1368                                 iovbuf, sizeof(iovbuf));
1369                         dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf,
1370                                 sizeof(iovbuf), TRUE, 0);
1371 #endif
1372 #ifdef DHD_ENABLE_LPC
1373                         /* Set lpc 0 */
1374                         bcm_mkiovar("lpc", (char *)&lpc, 4, iovbuf, sizeof(iovbuf));
1375                         if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf,
1376                                 sizeof(iovbuf), TRUE, 0)) < 0) {
1377                                 DHD_ERROR(("[WIFI_SEC] %s: Set lpc failed  %d\n",
1378                                 __FUNCTION__, ret));
1379                         }
1380 #endif /* DHD_ENABLE_LPC */
1381                 } else {
1382                         dhd_wl_ioctl_cmd(dhd, WLC_SET_PM, (char *)power_mode,
1383                                 sizeof(uint), TRUE, 0);
1384                 }
1385         }
1386
1387         if (fp)
1388                 filp_close(fp, NULL);
1389 }
1390 #endif /* CONFIG_CONTROL_PM */
1391
1392 #ifdef MIMO_ANT_SETTING
1393 int dhd_sel_ant_from_file(dhd_pub_t *dhd)
1394 {
1395         struct file *fp = NULL;
1396         int ret = -1;
1397         uint32 ant_val = 0;
1398         uint32 btc_mode = 0;
1399         char *filepath = ANTINFO;
1400         char iovbuf[WLC_IOCTL_SMLEN];
1401         uint chip_id = dhd_bus_chip_id(dhd);
1402
1403         /* Check if this chip can support MIMO */
1404         if (chip_id != BCM4324_CHIP_ID &&
1405                 chip_id != BCM4350_CHIP_ID &&
1406                 chip_id != BCM4356_CHIP_ID &&
1407                 chip_id != BCM4354_CHIP_ID) {
1408                 DHD_ERROR(("[WIFI_SEC] %s: This chipset does not support MIMO\n",
1409                         __FUNCTION__));
1410                 return ret;
1411         }
1412
1413         /* Read antenna settings from the file */
1414         fp = filp_open(filepath, O_RDONLY, 0);
1415         if (IS_ERR(fp)) {
1416                 DHD_ERROR(("[WIFI_SEC] %s: File [%s] open error\n", __FUNCTION__, filepath));
1417                 return ret;
1418         } else {
1419                 ret = kernel_read(fp, 0, (char *)&ant_val, 4);
1420                 if (ret < 0) {
1421                         DHD_ERROR(("[WIFI_SEC] %s: File read error, ret=%d\n", __FUNCTION__, ret));
1422                         filp_close(fp, NULL);
1423                         return ret;
1424                 }
1425
1426                 ant_val = bcm_atoi((char *)&ant_val);
1427
1428                 DHD_ERROR(("[WIFI_SEC]%s: ANT val = %d\n", __FUNCTION__, ant_val));
1429                 filp_close(fp, NULL);
1430
1431                 /* Check value from the file */
1432                 if (ant_val < 1 || ant_val > 3) {
1433                         DHD_ERROR(("[WIFI_SEC] %s: Invalid value %d read from the file %s\n",
1434                                 __FUNCTION__, ant_val, filepath));
1435                         return -1;
1436                 }
1437         }
1438
1439         /* bt coex mode off */
1440         if (dhd_get_fw_mode(dhd->info) == DHD_FLAG_MFG_MODE) {
1441                 bcm_mkiovar("btc_mode", (char *)&btc_mode, 4, iovbuf, sizeof(iovbuf));
1442                 ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0);
1443                 if (ret) {
1444                         DHD_ERROR(("[WIFI_SEC] %s: Fail to execute dhd_wl_ioctl_cmd(): "
1445                                 "btc_mode, ret=%d\n",
1446                                 __FUNCTION__, ret));
1447                         return ret;
1448                 }
1449         }
1450
1451         /* Select Antenna */
1452         bcm_mkiovar("txchain", (char *)&ant_val, 4, iovbuf, sizeof(iovbuf));
1453         ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0);
1454         if (ret) {
1455                 DHD_ERROR(("[WIFI_SEC] %s: Fail to execute dhd_wl_ioctl_cmd(): txchain, ret=%d\n",
1456                         __FUNCTION__, ret));
1457                 return ret;
1458         }
1459
1460         bcm_mkiovar("rxchain", (char *)&ant_val, 4, iovbuf, sizeof(iovbuf));
1461         ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0);
1462         if (ret) {
1463                 DHD_ERROR(("[WIFI_SEC] %s: Fail to execute dhd_wl_ioctl_cmd(): rxchain, ret=%d\n",
1464                         __FUNCTION__, ret));
1465                 return ret;
1466         }
1467
1468         return 0;
1469 }
1470 #endif /* MIMO_ANTENNA_SETTING */
1471
1472 #ifdef USE_WFA_CERT_CONF
1473 int sec_get_param(dhd_pub_t *dhd, int mode)
1474 {
1475         struct file *fp = NULL;
1476         char *filepath = NULL;
1477         int val, ret = 0;
1478
1479         if (!dhd || (mode < SET_PARAM_BUS_TXGLOM_MODE) ||
1480                 (mode >= PARAM_LAST_VALUE)) {
1481                 DHD_ERROR(("[WIFI_SEC] %s: invalid argument\n", __FUNCTION__));
1482                 return -EINVAL;
1483         }
1484
1485         switch (mode) {
1486                 case SET_PARAM_BUS_TXGLOM_MODE:
1487                         filepath = "/data/.bustxglom.info";
1488                         break;
1489                 case SET_PARAM_ROAMOFF:
1490                         filepath = "/data/.roamoff.info";
1491                         break;
1492 #ifdef USE_WL_FRAMEBURST
1493                 case SET_PARAM_FRAMEBURST:
1494                         filepath = "/data/.frameburst.info";
1495                         break;
1496 #endif /* USE_WL_FRAMEBURST */
1497 #ifdef USE_WL_TXBF
1498                 case SET_PARAM_TXBF:
1499                         filepath = "/data/.txbf.info";
1500                         break;
1501 #endif /* USE_WL_TXBF */
1502                 default:
1503                         return -EINVAL;
1504         }
1505
1506         fp = filp_open(filepath, O_RDONLY, 0);
1507         if (IS_ERR(fp) || (fp == NULL)) {
1508                 ret = -EIO;
1509         } else {
1510                 ret = kernel_read(fp, fp->f_pos, (char *)&val, 4);
1511                 filp_close(fp, NULL);
1512         }
1513
1514         if (ret < 0) {
1515                 /* File operation is failed so we will return default value */
1516                 switch (mode) {
1517                         case SET_PARAM_BUS_TXGLOM_MODE:
1518                                 val = CUSTOM_GLOM_SETTING;
1519                                 break;
1520                         case SET_PARAM_ROAMOFF:
1521 #ifdef ROAM_ENABLE
1522                                 val = 0;
1523 #elif defined(DISABLE_BUILTIN_ROAM)
1524                                 val = 1;
1525 #else
1526                                 val = 0;
1527 #endif /* ROAM_ENABLE */
1528                                 break;
1529 #ifdef USE_WL_FRAMEBURST
1530                         case SET_PARAM_FRAMEBURST:
1531                                 val = 1;
1532                                 break;
1533 #endif /* USE_WL_FRAMEBURST */
1534 #ifdef USE_WL_TXBF
1535                         case SET_PARAM_TXBF:
1536                                 val = 1;
1537                                 break;
1538 #endif /* USE_WL_TXBF */
1539                 }
1540
1541                 DHD_INFO(("[WIFI_SEC] %s: File open failed, file path=%s,"
1542                         " default value=%d\n",
1543                         __FUNCTION__, filepath, val));
1544                 return val;
1545         }
1546
1547         val = bcm_atoi((char *)&val);
1548         DHD_INFO(("[WIFI_SEC] %s: %s = %d\n", __FUNCTION__, filepath, val));
1549
1550         switch (mode) {
1551                 case SET_PARAM_ROAMOFF:
1552 #ifdef USE_WL_FRAMEBURST
1553                 case SET_PARAM_FRAMEBURST:
1554 #endif /* USE_WL_FRAMEBURST */
1555 #ifdef USE_WL_TXBF
1556                 case SET_PARAM_TXBF:
1557 #endif /* USE_WL_TXBF */
1558                         val = val ? 1 : 0;
1559                         break;
1560         }
1561
1562         return val;
1563 }
1564 #endif /* USE_WFA_CERT_CONF */
1565 #ifdef WRITE_WLANINFO
1566 #define FIRM_PREFIX "Firm_ver:"
1567 #define DHD_PREFIX "DHD_ver:"
1568 #define NV_PREFIX "Nv_info:"
1569 #define max_len(a, b) ((sizeof(a)/(2)) - (strlen(b)) - (3))
1570 #define tstr_len(a, b) ((strlen(a)) + (strlen(b)) + (3))
1571
1572 char version_info[512];
1573 char version_old_info[512];
1574
1575 int write_filesystem(struct file *file, unsigned long long offset,
1576         unsigned char* data, unsigned int size)
1577 {
1578         mm_segment_t oldfs;
1579         int ret;
1580
1581         oldfs = get_fs();
1582         set_fs(get_ds());
1583
1584         ret = vfs_write(file, data, size, &offset);
1585
1586         set_fs(oldfs);
1587         return ret;
1588 }
1589
1590 uint32 sec_save_wlinfo(char *firm_ver, char *dhd_ver, char *nvram_p)
1591 {
1592         struct file *fp = NULL;
1593         struct file *nvfp = NULL;
1594         char *filepath = WIFIVERINFO;
1595         int min_len, str_len = 0;
1596         int ret = 0;
1597         char* nvram_buf;
1598         char temp_buf[256];
1599
1600         DHD_TRACE(("[WIFI_SEC] %s: Entered.\n", __FUNCTION__));
1601
1602         DHD_INFO(("[WIFI_SEC] firmware version   : %s\n", firm_ver));
1603         DHD_INFO(("[WIFI_SEC] dhd driver version : %s\n", dhd_ver));
1604         DHD_INFO(("[WIFI_SEC] nvram path : %s\n", nvram_p));
1605
1606         memset(version_info, 0, sizeof(version_info));
1607
1608         if (strlen(dhd_ver)) {
1609                 min_len = min(strlen(dhd_ver), max_len(temp_buf, DHD_PREFIX));
1610                 min_len += strlen(DHD_PREFIX) + 3;
1611                 DHD_INFO(("[WIFI_SEC] DHD ver length : %d\n", min_len));
1612                 snprintf(version_info+str_len, min_len, DHD_PREFIX " %s\n", dhd_ver);
1613                 str_len = strlen(version_info);
1614
1615                 DHD_INFO(("[WIFI_SEC] Driver version_info len : %d\n", str_len));
1616                 DHD_INFO(("[WIFI_SEC] Driver version_info : %s\n", version_info));
1617         } else {
1618                 DHD_ERROR(("[WIFI_SEC] Driver version is missing.\n"));
1619         }
1620
1621         if (strlen(firm_ver)) {
1622                 min_len = min(strlen(firm_ver), max_len(temp_buf, FIRM_PREFIX));
1623                 min_len += strlen(FIRM_PREFIX) + 3;
1624                 DHD_INFO(("[WIFI_SEC] firmware ver length : %d\n", min_len));
1625                 snprintf(version_info+str_len, min_len, FIRM_PREFIX " %s\n", firm_ver);
1626                 str_len = strlen(version_info);
1627
1628                 DHD_INFO(("[WIFI_SEC] Firmware version_info len : %d\n", str_len));
1629                 DHD_INFO(("[WIFI_SEC] Firmware version_info : %s\n", version_info));
1630         } else {
1631                 DHD_ERROR(("[WIFI_SEC] Firmware version is missing.\n"));
1632         }
1633
1634         if (nvram_p) {
1635                 memset(temp_buf, 0, sizeof(temp_buf));
1636                 nvfp = filp_open(nvram_p, O_RDONLY, 0);
1637                 if (IS_ERR(nvfp) || (nvfp == NULL)) {
1638                         DHD_ERROR(("[WIFI_SEC] %s: Nvarm File open failed.\n", __FUNCTION__));
1639                         return -1;
1640                 } else {
1641                         ret = kernel_read(nvfp, nvfp->f_pos, temp_buf, sizeof(temp_buf));
1642                         filp_close(nvfp, NULL);
1643                 }
1644
1645                 if (strlen(temp_buf)) {
1646                         nvram_buf = temp_buf;
1647                         bcmstrtok(&nvram_buf, "\n", 0);
1648                         DHD_INFO(("[WIFI_SEC] nvram tolkening : %s(%zu) \n",
1649                                 temp_buf, strlen(temp_buf)));
1650                         snprintf(version_info+str_len, tstr_len(temp_buf, NV_PREFIX),
1651                                 NV_PREFIX " %s\n", temp_buf);
1652                         str_len = strlen(version_info);
1653                         DHD_INFO(("[WIFI_SEC] NVRAM version_info : %s\n", version_info));
1654                         DHD_INFO(("[WIFI_SEC] NVRAM version_info len : %d, nvram len : %zu\n",
1655                                 str_len, strlen(temp_buf)));
1656                 } else {
1657                         DHD_ERROR(("[WIFI_SEC] NVRAM info is missing.\n"));
1658                 }
1659         } else {
1660                 DHD_ERROR(("[WIFI_SEC] Not exist nvram path\n"));
1661         }
1662
1663         DHD_INFO(("[WIFI_SEC] version_info : %s, strlen : %zu\n",
1664                 version_info, strlen(version_info)));
1665
1666         fp = filp_open(filepath, O_RDONLY, 0);
1667         if (IS_ERR(fp) || (fp == NULL)) {
1668                 DHD_ERROR(("[WIFI_SEC] %s: .wifiver.info File open failed.\n", __FUNCTION__));
1669         } else {
1670                 memset(version_old_info, 0, sizeof(version_old_info));
1671                 ret = kernel_read(fp, fp->f_pos, version_old_info, sizeof(version_info));
1672                 filp_close(fp, NULL);
1673                 DHD_INFO(("[WIFI_SEC] kernel_read ret : %d.\n", ret));
1674                 if (strcmp(version_info, version_old_info) == 0) {
1675                         DHD_ERROR(("[WIFI_SEC] .wifiver.info already saved.\n"));
1676                         return 0;
1677                 }
1678         }
1679
1680         fp = filp_open(filepath, O_RDWR | O_CREAT, 0664);
1681         if (IS_ERR(fp) || (fp == NULL)) {
1682                 DHD_ERROR(("[WIFI_SEC] %s: .wifiver.info File open failed.\n",
1683                         __FUNCTION__));
1684         } else {
1685                 ret = write_filesystem(fp, fp->f_pos, version_info, sizeof(version_info));
1686                 DHD_INFO(("[WIFI_SEC] sec_save_wlinfo done. ret : %d\n", ret));
1687                 DHD_ERROR(("[WIFI_SEC] save .wifiver.info file.\n"));
1688                 filp_close(fp, NULL);
1689         }
1690         return ret;
1691 }
1692 #endif /* WRITE_WLANINFO */
1693 #endif /* CUSTOMER_HW4 */