1 #include <stdio.h>
2 #include <string.h>
3 #include "cc3000_common.h"
4 #include "nvmem.h"
5 #include "ccspi.h"
6 #include "hci.h"
7 #include "wlan.h"
8 #include "patch_prog.h"
9 #define BIT0 0x1
10 #define BIT1 0x2
11 #define BIT2 0x4
12 #define BIT3 0x8
13 #define BIT4 0x10
14 #define BIT5 0x20
15 #define BIT6 0x40
16 #define BIT7 0x80
17
18 static unsigned char ucStatus_Dr;
19 static unsigned char ucStatus_FW;
20 static unsigned char return_status = 0xFF;
21
22 static signed char mac_status = -1;
23 static unsigned char counter = 0;
24
25 // Array to store RM parameters from EEPROM.
26 static unsigned char cRMParamsFromEeprom[128];
27 // Array to store MAC address from EEPROM.
28 static unsigned char cMacFromEeprom[MAC_ADDR_LEN];
29 // Smart Config Prefix
30 static const char aucCC3000_prefix[] = {'T', 'T', 'T'};
31
systick_sleep(unsigned long ms)32 static void systick_sleep(unsigned long ms) {
33 extern void HAL_Delay(volatile uint32_t Delay);
34 HAL_Delay(ms);
35 }
36
37 // 2 dim array to store address and length of new FAT
38 static const unsigned short aFATEntries[2][NVMEM_RM_FILEID + 1] =
39 /* address */ {{0x50, 0x1f0, 0x390, 0x1390, 0x2390, 0x4390, 0x6390, 0x63a0, 0x63b0, 0x63f0, 0x6430, 0x6830},
40 /* length */ {0x1a0, 0x1a0, 0x1000, 0x1000, 0x2000, 0x2000, 0x10, 0x10, 0x40, 0x40, 0x400, 0x200}};
41 /* 0. NVS */
42 /* 1. NVS Shadow */
43 /* 2. Wireless Conf */
44 /* 3. Wireless Conf Shadow */
45 /* 4. BT (WLAN driver) Patches */
46 /* 5. WiLink (Firmware) Patches */
47 /* 6. MAC addr */
48 /* 7. Frontend Vars */
49 /* 8. IP config */
50 /* 9. IP config Shadow */
51 /* 10. Bootloader Patches */
52 /* 11. Radio Module params */
53 /* 12. AES128 for smart config */
54 /* 13. user file */
55 /* 14. user file */
56 /* 15. user file */
57
58 //*****************************************************************************
59 //
60 //! sendDriverPatch
61 //!
62 //! \param pointer to the length
63 //!
64 //! \return none
65 //!
66 //! \brief The function returns a pointer to the driver patch:
67 //! since there is no patch yet - it returns 0
68 //
69 //*****************************************************************************
70
sendDriverPatch(unsigned long * Length)71 static char *sendDriverPatch(unsigned long *Length)
72 {
73 *Length = 0;
74 return NULL;
75 }
76
77
78 //*****************************************************************************
79 //
80 //! sendBootLoaderPatch
81 //!
82 //! \param pointer to the length
83 //!
84 //! \return none
85 //!
86 //! \brief The function returns a pointer to the boot loader patch:
87 //! since there is no patch yet - it returns 0
88 //
89 //*****************************************************************************
90
sendBootLoaderPatch(unsigned long * Length)91 static char *sendBootLoaderPatch(unsigned long *Length)
92 {
93 *Length = 0;
94 return NULL;
95 }
96
97 //*****************************************************************************
98 //
99 //! sendWLFWPatch
100 //!
101 //! \param pointer to the length
102 //!
103 //! \return none
104 //!
105 //! \brief The function returns a pointer to the FW patch:
106 //! since there is no patch yet - it returns 0
107 //
108 //*****************************************************************************
109
sendWLFWPatch(unsigned long * Length)110 static char *sendWLFWPatch(unsigned long *Length)
111 {
112 *Length = 0;
113 return NULL;
114 }
115
116 //*****************************************************************************
117 //
118 //! CC3000_UsynchCallback
119 //!
120 //! \param Event type
121 //!
122 //! \return none
123 //!
124 //! \brief The function handles asynchronous events that come from CC3000
125 //! device and operates a LED4 to have an on-board indication
126 //
127 //*****************************************************************************
128
CC3000_UsynchCallback(long lEventType,char * data,unsigned char length)129 static void CC3000_UsynchCallback(long lEventType, char * data, unsigned char length)
130 {
131
132 }
133
134 //*****************************************************************************
135 //
136 //! initDriver
137 //!
138 //! \param[in] cRequestPatch 0 to load with EEPROM patches
139 //! and 1 to load with no patches
140 //!
141 //! \return none
142 //!
143 //! \brief The function initializes a CC3000 device
144 //! and triggers it to start operation
145 //
146 //*****************************************************************************
initDriver(unsigned short cRequestPatch)147 static int initDriver(unsigned short cRequestPatch)
148 {
149 // WLAN On API Implementation
150 wlan_init(CC3000_UsynchCallback, sendWLFWPatch, sendDriverPatch, sendBootLoaderPatch,
151 ReadWlanInterruptPin, SpiResumeSpi, SpiPauseSpi, WriteWlanPin);
152
153 // Trigger a WLAN device
154 wlan_start(cRequestPatch);
155 wlan_smart_config_set_prefix((char*)aucCC3000_prefix);
156 wlan_ioctl_set_connection_policy(0, 0, 0);
157 wlan_ioctl_del_profile(255);
158
159 // Mask out all non-required events from CC3000
160 wlan_set_event_mask(HCI_EVNT_WLAN_KEEPALIVE|
161 HCI_EVNT_WLAN_UNSOL_INIT|
162 HCI_EVNT_WLAN_ASYNC_PING_REPORT);
163
164 //unsolicicted_events_timer_init();
165 systick_sleep(100);
166 return(0);
167 }
168
169
170 //*****************************************************************************
171 //
172 //! fat_read_content
173 //!
174 //! \param[out] is_allocated array of is_allocated in FAT table:\n
175 //! an allocated entry implies the address and length of the
176 //! file are valid.
177 //! 0: not allocated; 1: allocated.
178 //! \param[out] is_valid array of is_valid in FAT table:\n
179 //! a valid entry implies the content of the file is relevant.
180 //! 0: not valid; 1: valid.
181 //! \param[out] write_protected array of write_protected in FAT table:\n
182 //! a write protected entry implies it is not possible to write
183 //! into this entry.
184 //! 0: not protected; 1: protected.
185 //! \param[out] file_address array of file address in FAT table:\n
186 //! this is the absolute address of the file in the EEPROM.
187 //! \param[out] file_length array of file length in FAT table:\n
188 //! this is the upper limit of the file size in the EEPROM.
189 //!
190 //! \return on succes 0, error otherwise
191 //!
192 //! \brief parse the FAT table from eeprom
193 //
194 //*****************************************************************************
195 static unsigned char __attribute__ ((unused))
fat_read_content(unsigned char * is_allocated,unsigned char * is_valid,unsigned char * write_protected,unsigned short * file_address,unsigned short * file_length)196 fat_read_content(unsigned char *is_allocated, unsigned char *is_valid,
197 unsigned char *write_protected, unsigned short *file_address, unsigned short *file_length)
198 {
199 unsigned short index;
200 unsigned char ucStatus;
201 unsigned char fatTable[48];
202 unsigned char* fatTablePtr = fatTable;
203
204 //
205 // Read in 6 parts to work with tiny driver
206 //
207 for (index = 0; index < 6; index++)
208 {
209 ucStatus = nvmem_read(16, 8, 4 + 8*index, fatTablePtr);
210 fatTablePtr += 8;
211 }
212
213 fatTablePtr = fatTable;
214
215 for (index = 0; index <= NVMEM_RM_FILEID; index++)
216 {
217 *is_allocated++ = (*fatTablePtr) & BIT0;
218 *is_valid++ = ((*fatTablePtr) & BIT1) >> 1;
219 *write_protected++ = ((*fatTablePtr) & BIT2) >> 2;
220 *file_address++ = ((*(fatTablePtr+1)<<8) | (*fatTablePtr)) & (BIT4|BIT5|BIT6|BIT7);
221 *file_length++ = ((*(fatTablePtr+3)<<8) | (*(fatTablePtr+2))) & (BIT4|BIT5|BIT6|BIT7);
222
223 //
224 // Move to next file ID
225 //
226 fatTablePtr += 4;
227 }
228
229 return ucStatus;
230 }
231
232 //*****************************************************************************
233 //
234 //! fat_write_content
235 //!
236 //! \param[in] file_address array of file address in FAT table:\n
237 //! this is the absolute address of the file in the EEPROM.
238 //! \param[in] file_length array of file length in FAT table:\n
239 //! this is the upper limit of the file size in the EEPROM.
240 //!
241 //! \return on succes 0, error otherwise
242 //!
243 //! \brief parse the FAT table from eeprom
244 //
245 //*****************************************************************************
fat_write_content(unsigned short const * file_address,unsigned short const * file_length)246 static unsigned char fat_write_content(unsigned short const *file_address,
247 unsigned short const *file_length)
248 {
249 unsigned short index = 0;
250 unsigned char ucStatus;
251 unsigned char fatTable[48];
252 unsigned char* fatTablePtr = fatTable;
253
254 //
255 // First, write the magic number.
256 //
257 ucStatus = nvmem_write(16, 2, 0, (unsigned char*)"LS");
258
259 for (; index <= NVMEM_RM_FILEID; index++)
260 {
261 //
262 // Write address low char and mark as allocated.
263 //
264 *fatTablePtr++ = (unsigned char)(file_address[index] & 0xff) | BIT0;
265
266 //
267 // Write address high char.
268 //
269 *fatTablePtr++ = (unsigned char)((file_address[index]>>8) & 0xff);
270
271 //
272 // Write length low char.
273 //
274 *fatTablePtr++ = (unsigned char)(file_length[index] & 0xff);
275
276 //
277 // Write length high char.
278 //
279 *fatTablePtr++ = (unsigned char)((file_length[index]>>8) & 0xff);
280 }
281
282 //
283 // Second, write the FAT.
284 // Write in two parts to work with tiny driver.
285 //
286 ucStatus = nvmem_write(16, 24, 4, fatTable);
287 ucStatus = nvmem_write(16, 24, 24+4, &fatTable[24]);
288
289 //
290 // Third, we want to erase any user files.
291 //
292 memset(fatTable, 0, sizeof(fatTable));
293 ucStatus = nvmem_write(16, 16, 52, fatTable);
294
295 return ucStatus;
296 }
297
patch_prog_start()298 void patch_prog_start()
299 {
300 unsigned short index;
301 unsigned char *pRMParams;
302
303 printf("Initializing module...\n");
304
305 // Init module and request to load with no patches.
306 // This is in order to overwrite restrictions to
307 // write to specific places in EEPROM.
308 initDriver(1);
309
310 // Read MAC address.
311 mac_status = nvmem_get_mac_address(cMacFromEeprom);
312
313 return_status = 1;
314
315 printf("Reading RM parameters...\n");
316 while ((return_status) && (counter < 3)) {
317 // Read RM parameters.
318 // Read in 16 parts to work with tiny driver.
319 return_status = 0;
320 pRMParams = cRMParamsFromEeprom;
321 for (index = 0; index < 16; index++) {
322 return_status |= nvmem_read(NVMEM_RM_FILEID, 8, 8*index, pRMParams);
323 pRMParams += 8;
324 }
325 counter++;
326 }
327
328 // If RM file is not valid, load the default one.
329 if (counter == 3) {
330 printf("RM is not valid, loading default one...\n");
331 pRMParams = (unsigned char *)cRMdefaultParams;
332 } else {
333 printf("RM is valid.\n");
334 pRMParams = cRMParamsFromEeprom;
335 }
336
337 return_status = 1;
338
339 printf("Writing new FAT\n");
340 while (return_status) {
341 // Write new FAT.
342 return_status = fat_write_content(aFATEntries[0], aFATEntries[1]);
343 }
344
345 return_status = 1;
346
347 printf("Writing RM parameters...\n");
348 while (return_status) {
349 // Write RM parameters.
350 // Write in 4 parts to work with tiny driver.
351 return_status = 0;
352
353 for (index = 0; index < 4; index++) {
354 return_status |= nvmem_write(NVMEM_RM_FILEID,
355 32,
356 32*index,
357 (pRMParams + 32*index));
358 }
359 }
360
361 return_status = 1;
362
363 // Write back the MAC address, only if exists.
364 if (mac_status == 0) {
365 // Zero out MCAST bit if set.
366 cMacFromEeprom[0] &= 0xfe;
367 printf("Writing back MAC address..\n");
368 while (return_status) {
369 return_status = nvmem_set_mac_address(cMacFromEeprom);
370 }
371 }
372
373 // Update driver
374 ucStatus_Dr = 1;
375 printf("Updating driver patch...\n");
376 while (ucStatus_Dr) {
377 // Writing driver patch to EEPRROM - PROTABLE CODE
378 // Note that the array itself is changing between the
379 // different Service Packs.
380 ucStatus_Dr = nvmem_write_patch(NVMEM_WLAN_DRIVER_SP_FILEID,
381 drv_length,
382 wlan_drv_patch);
383 }
384
385 // Update firmware
386 ucStatus_FW = 1;
387 printf("Updating firmware patch...\n");
388 while (ucStatus_FW) {
389 // Writing FW patch to EEPRROM - PROTABLE CODE
390 // Note that the array itself is changing between the
391 // different Service Packs.
392 ucStatus_FW = nvmem_write_patch(NVMEM_WLAN_FW_SP_FILEID,
393 fw_length,
394 fw_patch);
395 }
396
397 printf("Update complete, resetting module\n"\
398 "If this doesn't work, reset manually...\n");
399
400 wlan_stop();
401 systick_sleep(500);
402
403 // Re-Init module and request to load with patches.
404 initDriver(0);
405
406 // If MAC does not exist, it is recommended
407 // that the user will write a valid mac address.
408 if (mac_status != 0) {
409 printf("MAC address is not valid, please write a new one\n");
410 }
411
412 // Patch update done
413 printf("All done, call wlan.patch_version()\n");
414 }
415