1 /*
2  * File      : wifi_config.c
3  * This file is part of RT-Thread RTOS
4  * COPYRIGHT (C) 2006 - 2018, RT-Thread Development Team
5  *
6  *  This program is free software; you can redistribute it and/or modify
7  *  it under the terms of the GNU General Public License as published by
8  *  the Free Software Foundation; either version 2 of the License, or
9  *  (at your option) any later version.
10  *
11  *  This program is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *  GNU General Public License for more details.
15  *
16  *  You should have received a copy of the GNU General Public License along
17  *  with this program; if not, write to the Free Software Foundation, Inc.,
18  *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19  *
20  * Change Logs:
21  * Date           Author       Notes
22  * 2018-09-04     ZeroFree     first implementation
23  * 2019-06-14     armink       add easyflash v4.0 support
24  */
25 
26 #include <rtthread.h>
27 
28 #ifdef BSP_USING_WIFI
29 
30 #include <dev_wlan_mgnt.h>
31 #include <dev_wlan_cfg.h>
32 #include <dev_wlan_prot.h>
33 
34 #include <easyflash.h>
35 #include <fal.h>
36 
37 #include <stdio.h>
38 #include <stdlib.h>
39 
40 #if (EF_SW_VERSION_NUM < 0x40000)
41 
42 static char *str_base64_encode_len(const void *src, char *out, int input_length);
43 static int   str_base64_decode(const char *data, int input_length, char *decoded_data);
44 
45 static const unsigned char base64_table[65] =
46     "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
47 
48 static const char base64_decode_table[256] =
49 {
50     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
51     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
52     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x3F,
53     0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
54     0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E,
55     0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00,
56     0x00, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28,
57     0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x32, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00,
58     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
59     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
60     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
61     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
62     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
63     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
64     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
65     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
66 };
67 
str_base64_encode_len(const void * src,char * out,int len)68 static char *str_base64_encode_len(const void *src, char *out, int len)
69 {
70     unsigned char *pos;
71     const unsigned char *end, *in;
72     size_t olen;
73 
74     olen = len * 4 / 3 + 4; /* 3-byte blocks to 4-byte */
75     olen += olen / 72; /* line feeds */
76     olen++; /* nul termination */
77 
78     end = (const unsigned char *)src + len;
79     in = (const unsigned char *)src;
80     pos = (unsigned char *)out;
81     while (end - in >= 3)
82     {
83         *pos++ = base64_table[in[0] >> 2];
84         *pos++ = base64_table[((in[0] & 0x03) << 4) | (in[1] >> 4)];
85         *pos++ = base64_table[((in[1] & 0x0f) << 2) | (in[2] >> 6)];
86         *pos++ = base64_table[in[2] & 0x3f];
87         in += 3;
88     }
89 
90     if (end - in)
91     {
92         *pos++ = base64_table[in[0] >> 2];
93 
94         if (end - in == 1)
95         {
96             *pos++ = base64_table[(in[0] & 0x03) << 4];
97             *pos++ = '=';
98         }
99         else
100         {
101             *pos++ = base64_table[((in[0] & 0x03) << 4) |
102                                                   (in[1] >> 4)];
103             *pos++ = base64_table[(in[1] & 0x0f) << 2];
104         }
105         *pos++ = '=';
106     }
107 
108     *pos = '\0';
109     return (char *)out;
110 }
111 
112 /*
113  * return: length, 0 is error.
114  */
str_base64_decode(const char * data,int input_length,char * decoded_data)115 static int str_base64_decode(const char *data, int input_length, char *decoded_data)
116 {
117     int out_len;
118     int i, j;
119 
120     if (input_length % 4 != 0) return 0;
121 
122     out_len = input_length / 4 * 3;
123 
124     if (data[input_length - 1] == '=') out_len--;
125     if (data[input_length - 2] == '=') out_len--;
126 
127     for (i = 0, j = 0; i < input_length;)
128     {
129         uint32_t sextet_a = data[i] == '=' ? 0 & i++ : base64_decode_table[data[i++]];
130         uint32_t sextet_b = data[i] == '=' ? 0 & i++ : base64_decode_table[data[i++]];
131         uint32_t sextet_c = data[i] == '=' ? 0 & i++ : base64_decode_table[data[i++]];
132         uint32_t sextet_d = data[i] == '=' ? 0 & i++ : base64_decode_table[data[i++]];
133 
134         uint32_t triple = (sextet_a << 3 * 6)
135                           + (sextet_b << 2 * 6)
136                           + (sextet_c << 1 * 6)
137                           + (sextet_d << 0 * 6);
138 
139         if (j < out_len) decoded_data[j++] = (triple >> 2 * 8) & 0xFF;
140         if (j < out_len) decoded_data[j++] = (triple >> 1 * 8) & 0xFF;
141         if (j < out_len) decoded_data[j++] = (triple >> 0 * 8) & 0xFF;
142     }
143 
144     return out_len;
145 }
146 
read_cfg(void * buff,int len)147 static int read_cfg(void *buff, int len)
148 {
149     char *wlan_cfg_info = RT_NULL;
150 
151     wlan_cfg_info = ef_get_env("wlan_cfg_info");
152     if (wlan_cfg_info != RT_NULL)
153     {
154         str_base64_decode(wlan_cfg_info, rt_strlen(wlan_cfg_info), buff);
155         return len;
156     }
157     else
158     {
159         return 0;
160     }
161 }
162 
get_len(void)163 static int get_len(void)
164 {
165     int len;
166     char *wlan_cfg_len = RT_NULL;
167 
168     wlan_cfg_len = ef_get_env("wlan_cfg_len");
169     if (wlan_cfg_len == RT_NULL)
170     {
171         len = 0;
172     }
173     else
174     {
175         len = atoi(wlan_cfg_len);
176     }
177 
178     return len;
179 }
180 
write_cfg(void * buff,int len)181 static int write_cfg(void *buff, int len)
182 {
183     char wlan_cfg_len[12] = {0};
184     char *base64_buf = RT_NULL;
185 
186     base64_buf = rt_malloc(len * 4 / 3 + 4); /* 3-byte blocks to 4-byte, and the end. */
187     if (base64_buf == RT_NULL)
188     {
189         return -RT_ENOMEM;
190     }
191     rt_memset(base64_buf, 0, len);
192 
193     /* interger to string */
194     sprintf(wlan_cfg_len, "%d", len);
195     /* set and store the wlan config lengths to Env */
196     ef_set_env("wlan_cfg_len", wlan_cfg_len);
197     str_base64_encode_len(buff, base64_buf, len);
198     /* set and store the wlan config information to Env */
199     ef_set_env("wlan_cfg_info", base64_buf);
200     ef_save_env();
201     rt_free(base64_buf);
202 
203     return len;
204 }
205 
206 #else
207 
read_cfg(void * buff,int len)208 static int read_cfg(void *buff, int len)
209 {
210     size_t saved_len;
211 
212     ef_get_env_blob("wlan_cfg_info", buff, len, &saved_len);
213     if (saved_len == 0)
214     {
215         return 0;
216     }
217     return len;
218 }
219 
get_len(void)220 static int get_len(void)
221 {
222     int len;
223     size_t saved_len;
224 
225     ef_get_env_blob("wlan_cfg_len", &len, sizeof(len), &saved_len);
226     if (saved_len == 0)
227     {
228         return 0;
229     }
230 
231     return len;
232 }
233 
write_cfg(void * buff,int len)234 static int write_cfg(void *buff, int len)
235 {
236     /* set and store the wlan config lengths to Env */
237     ef_set_env_blob("wlan_cfg_len", &len, sizeof(len));
238 
239     /* set and store the wlan config information to Env */
240     ef_set_env_blob("wlan_cfg_info", buff, len);
241 
242     return len;
243 }
244 
245 #endif /* (EF_SW_VERSION_NUM < 0x40000) */
246 
247 static const struct rt_wlan_cfg_ops ops =
248 {
249     read_cfg,
250     get_len,
251     write_cfg
252 };
253 
wlan_autoconnect_init(void)254 void wlan_autoconnect_init(void)
255 {
256     fal_init();
257     easyflash_init();
258 
259     rt_wlan_cfg_set_ops(&ops);
260     rt_wlan_cfg_cache_refresh();
261 }
262 
263 #endif
264