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