• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /******************************************************************************
2  *
3  *  Copyright (C) 2012 Broadcom Corporation
4  *
5  *  Licensed under the Apache License, Version 2.0 (the "License");
6  *  you may not use this file except in compliance with the License.
7  *  You may obtain a copy of the License at:
8  *
9  *  http://www.apache.org/licenses/LICENSE-2.0
10  *
11  *  Unless required by applicable law or agreed to in writing, software
12  *  distributed under the License is distributed on an "AS IS" BASIS,
13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  *  See the License for the specific language governing permissions and
15  *  limitations under the License.
16  *
17  ******************************************************************************/
18 #include <string.h>
19 #include "nfc_hal_int.h"
20 #include "userial.h"
21 
22 /*****************************************************************************
23 * Definitions
24 *****************************************************************************/
25 
26 /* Internal flags */
27 #define NFC_HAL_PRM_FLAGS_USE_PATCHRAM_BUF  0x01    /* Application provided patchram in a single buffer */
28 #define NFC_HAL_PRM_FLAGS_RFU               0x02    /* Reserved for future use */
29 #define NFC_HAL_PRM_FLAGS_SIGNATURE_SENT    0x04    /* Signature sent to NFCC */
30 #define NFC_HAL_PRM_FLAGS_I2C_FIX_REQUIRED  0x08    /* PreI2C patch required */
31 #define NFC_HAL_PRM_FLAGS_NO_NVM            0x10    /* Not NVM available (patch downloaded to SRAM) */
32 #define NFC_HAL_PRM_FLAGS_SUPPORT_RESET_NTF 0x20    /* Support RESET_NTF from NFCC after sending signature */
33 #define NFC_HAL_PRM_FLAGS_NVM_FPM_CORRUPTED 0x40    /* FPM patch in NVM failed CRC check */
34 #define NFC_HAL_PRM_FLAGS_NVM_LPM_CORRUPTED 0x80    /* LPM patch in NVM failed CRC check */
35 
36 /* Secure patch download definitions */
37 #define NFC_HAL_PRM_NCD_PATCHFILE_HDR_LEN  7       /* PRJID + MAJORVER + MINORVER + COUNT */
38 #define NFC_HAL_PRM_NCD_PATCH_VERSION_LEN  16
39 
40 #define NFC_HAL_PRM_SPD_PRE_DOWNLOAD_DELAY (500)   /* Delay before starting to patch download (in ms) */
41 
42 /* Enumeration of power modes IDs */
43 #define NFC_HAL_PRM_SPD_POWER_MODE_LPM     0
44 #define NFC_HAL_PRM_SPD_POWER_MODE_FPM     1
45 
46 /* Version string for BCM20791B3 */
47 const UINT8 NFC_HAL_PRM_BCM20791B3_STR[]   = "20791B3";
48 #define NFC_HAL_PRM_BCM20791B3_STR_LEN     (sizeof (NFC_HAL_PRM_BCM20791B3_STR)-1)
49 
50 #define NFC_HAL_PRM_SPD_TOUT                   (6000)  /* timeout for SPD events (in ms)   */
51 #define NFC_HAL_PRM_END_DELAY                  (250)   /* delay before sending any new command (ms)*/
52 
53 /* command to get currently downloaded patch version */
54 static UINT8 nfc_hal_prm_get_patch_version_cmd [NCI_MSG_HDR_SIZE] =
55 {
56     NCI_MTS_CMD|NCI_GID_PROP,
57     NCI_MSG_GET_PATCH_VERSION,
58     0x00
59 };
60 
61 #if (NFC_HAL_PRM_DEBUG == TRUE)
62 #define NFC_HAL_PRM_STATE(str)  NCI_TRACE_DEBUG2 ("%s st: %d", str, nfc_hal_cb.prm.state)
63 #else
64 #define NFC_HAL_PRM_STATE(str)
65 #endif
66 
67 void nfc_hal_prm_post_baud_update (tHAL_NFC_STATUS status);
68 
69 /*****************************************************************************
70 ** Extern variable from nfc_hal_dm_cfg.c
71 *****************************************************************************/
72 extern BOOLEAN nfc_hal_prm_nvm_required;
73 
74 /*******************************************************************************
75 **
76 ** Function         nfc_hal_prm_spd_handle_download_complete
77 **
78 ** Description      Patch download complete (for secure patch download)
79 **
80 ** Returns          void
81 **
82 *******************************************************************************/
nfc_hal_prm_spd_handle_download_complete(UINT8 event)83 void nfc_hal_prm_spd_handle_download_complete (UINT8 event)
84 {
85     nfc_hal_cb.prm.state = NFC_HAL_PRM_ST_IDLE;
86 
87     /* Notify application now */
88     if (nfc_hal_cb.prm.p_cback)
89         (nfc_hal_cb.prm.p_cback) (event);
90 }
91 
92 /*******************************************************************************
93 **
94 ** Function         nfc_hal_prm_spd_send_next_segment
95 **
96 ** Description      Send next patch segment (for secure patch download)
97 **
98 ** Returns          void
99 **
100 *******************************************************************************/
nfc_hal_prm_spd_send_next_segment(void)101 void nfc_hal_prm_spd_send_next_segment (void)
102 {
103     UINT8   *p_src;
104     UINT16  len, offset = nfc_hal_cb.prm.cur_patch_offset;
105     UINT8   hcit, oid, hdr0, type;
106     UINT8   chipverlen;
107     UINT8   chipverstr[NCI_SPD_HEADER_CHIPVER_LEN];
108     UINT8   patch_hdr_size = NCI_MSG_HDR_SIZE + 1; /* 1 is for HCIT */
109 
110     /* Validate that segment is at least big enought to have NCI_MSG_HDR_SIZE + 1 (hcit) */
111     if (nfc_hal_cb.prm.cur_patch_len_remaining < patch_hdr_size)
112     {
113         NCI_TRACE_ERROR0 ("Unexpected end of patch.");
114         nfc_hal_prm_spd_handle_download_complete (NFC_HAL_PRM_ABORT_INVALID_PATCH_EVT);
115         return;
116     }
117 
118     /* Parse NCI command header */
119     p_src = (UINT8*) (nfc_hal_cb.prm.p_cur_patch_data + offset);
120     STREAM_TO_UINT8 (hcit, p_src);
121     STREAM_TO_UINT8 (hdr0, p_src);
122     STREAM_TO_UINT8 (oid,  p_src);
123     STREAM_TO_UINT8 (len,  p_src);
124     STREAM_TO_UINT8 (type, p_src);
125 
126 
127     /* Update number of bytes comsumed */
128     nfc_hal_cb.prm.cur_patch_offset += (len + patch_hdr_size);
129     nfc_hal_cb.prm.cur_patch_len_remaining -=  (len + patch_hdr_size);
130 
131     /* Check if sending signature byte */
132     if (  (oid == NCI_MSG_SECURE_PATCH_DOWNLOAD )
133         &&(type == NCI_SPD_TYPE_SIGNATURE)  )
134     {
135         nfc_hal_cb.prm.flags |= NFC_HAL_PRM_FLAGS_SIGNATURE_SENT;
136     }
137     /* Check for header */
138     else if (  (oid == NCI_MSG_SECURE_PATCH_DOWNLOAD )
139              &&(type == NCI_SPD_TYPE_HEADER)  )
140     {
141         /* Check if patch is for BCM20791B3 */
142         p_src += NCI_SPD_HEADER_OFFSET_CHIPVERLEN;
143         STREAM_TO_UINT8 (chipverlen, p_src);
144         STREAM_TO_ARRAY (chipverstr, p_src, NCI_SPD_HEADER_CHIPVER_LEN);
145 
146         if (memcmp (NFC_HAL_PRM_BCM20791B3_STR, chipverstr, NFC_HAL_PRM_BCM20791B3_STR_LEN) == 0)
147         {
148             /* Patch is for BCM2079B3 - do not wait for RESET_NTF after patch download */
149             nfc_hal_cb.prm.flags &= ~NFC_HAL_PRM_FLAGS_SUPPORT_RESET_NTF;
150         }
151         else
152         {
153             /* Patch is for BCM2079B4 or newer - wait for RESET_NTF after patch download */
154             nfc_hal_cb.prm.flags |= NFC_HAL_PRM_FLAGS_SUPPORT_RESET_NTF;
155         }
156     }
157 
158     /* Send the command (not including HCIT here) */
159     nfc_hal_dm_send_nci_cmd ((UINT8*) (nfc_hal_cb.prm.p_cur_patch_data + offset + 1), (UINT8) (len + NCI_MSG_HDR_SIZE),
160                              nfc_hal_prm_nci_command_complete_cback);
161 }
162 
163 /*******************************************************************************
164 **
165 ** Function         nfc_hal_prm_spd_handle_next_patch_start
166 **
167 ** Description      Handle start of next patch (for secure patch download)
168 **
169 ** Returns          void
170 **
171 *******************************************************************************/
nfc_hal_prm_spd_handle_next_patch_start(void)172 void nfc_hal_prm_spd_handle_next_patch_start (void)
173 {
174     UINT32  cur_patch_mask;
175     UINT32  cur_patch_len;
176     BOOLEAN found_patch_to_download = FALSE;
177 
178     while (!found_patch_to_download)
179     {
180         /* Get length of current patch */
181         cur_patch_len = nfc_hal_cb.prm.spd_patch_desc[nfc_hal_cb.prm.spd_cur_patch_idx].len;
182 
183         /* Check if this is a patch we need to download */
184         cur_patch_mask = ((UINT32) 1 << nfc_hal_cb.prm.spd_patch_desc[nfc_hal_cb.prm.spd_cur_patch_idx].power_mode);
185         if (nfc_hal_cb.prm.spd_patch_needed_mask & cur_patch_mask)
186         {
187             found_patch_to_download = TRUE;
188         }
189         else
190         {
191             /* Do not need to download this patch. Skip to next patch */
192             NCI_TRACE_DEBUG1 ("Skipping patch for power_mode %i.", nfc_hal_cb.prm.spd_patch_desc[nfc_hal_cb.prm.spd_cur_patch_idx].power_mode);
193 
194             nfc_hal_cb.prm.spd_cur_patch_idx++;
195             if (nfc_hal_cb.prm.spd_cur_patch_idx >= nfc_hal_cb.prm.spd_patch_count)
196             {
197                 /* No more to download */
198                 nfc_hal_prm_spd_handle_download_complete (NFC_HAL_PRM_COMPLETE_EVT);
199                 return;
200             }
201             else if (!(nfc_hal_cb.prm.flags & NFC_HAL_PRM_FLAGS_USE_PATCHRAM_BUF))
202             {
203                 /* Notify adaptation layer to call HAL_NfcPrmDownloadContinue with the next patch header */
204                 (nfc_hal_cb.prm.p_cback) (NFC_HAL_PRM_SPD_GET_NEXT_PATCH);
205                 return;
206             }
207             else
208             {
209                 /* Patch in buffer. Skip over current patch. Check next patch */
210                 nfc_hal_cb.prm.cur_patch_len_remaining -= (UINT16) cur_patch_len;
211                 nfc_hal_cb.prm.cur_patch_offset += (UINT16) cur_patch_len;
212             }
213         }
214     }
215 
216 
217     /* Begin downloading patch */
218     NCI_TRACE_DEBUG1 ("Downloading patch for power_mode %i.", nfc_hal_cb.prm.spd_patch_desc[nfc_hal_cb.prm.spd_cur_patch_idx].power_mode);
219     nfc_hal_cb.prm.state = NFC_HAL_PRM_ST_SPD_DOWNLOADING;
220     nfc_hal_prm_spd_send_next_segment ();
221 }
222 
223 #if (defined (NFC_HAL_PRE_I2C_PATCH_INCLUDED) && (NFC_HAL_PRE_I2C_PATCH_INCLUDED == TRUE))
224 /*******************************************************************************
225 **
226 ** Function         nfc_hal_prm_spd_download_i2c_fix
227 **
228 ** Description      Start downloading patch for i2c fix
229 **
230 ** Returns          void
231 **
232 *******************************************************************************/
nfc_hal_prm_spd_download_i2c_fix(void)233 void nfc_hal_prm_spd_download_i2c_fix (void)
234 {
235     UINT8 *p, *p_start;
236     UINT16 patchfile_project_id;
237     UINT16 patchfile_ver_major;
238     UINT16 patchfile_ver_minor;
239     UINT16 patchfile_patchsize;
240     UINT8 u8;
241 
242     NCI_TRACE_DEBUG0 ("Downloading I2C fix...");
243 
244     /* Save pointer and offset of patchfile, so we can resume after downloading the i2c fix */
245     nfc_hal_cb.prm.spd_patch_offset = nfc_hal_cb.prm.cur_patch_offset;
246     nfc_hal_cb.prm.spd_patch_len_remaining = nfc_hal_cb.prm.cur_patch_len_remaining;
247 
248     /* Initialize pointers for downloading i2c fix */
249     nfc_hal_cb.prm.p_cur_patch_data = nfc_hal_cb.prm_i2c.p_patch;
250     nfc_hal_cb.prm.cur_patch_offset = 0;
251     nfc_hal_cb.prm.cur_patch_len_remaining = nfc_hal_cb.prm_i2c.len;
252 
253     /* Parse the i2c patchfile */
254     if (nfc_hal_cb.prm.cur_patch_len_remaining >= NFC_HAL_PRM_NCD_PATCHFILE_HDR_LEN)
255     {
256         /* Parse patchfile header */
257         p = (UINT8 *) nfc_hal_cb.prm.p_cur_patch_data;
258         p_start = p;
259         STREAM_TO_UINT16 (patchfile_project_id, p);
260         STREAM_TO_UINT16 (patchfile_ver_major, p);
261         STREAM_TO_UINT16 (patchfile_ver_minor, p);
262 
263         /* RFU */
264         p++;
265 
266         /* Check how many patches are in the patch file */
267         STREAM_TO_UINT8 (u8, p);
268 
269         /* Should only be one patch */
270         if (u8 > 1)
271         {
272             NCI_TRACE_ERROR1 ("Invalid i2c fix: invalid number of patches (%i)", u8);
273             nfc_hal_prm_spd_handle_download_complete (NFC_HAL_PRM_ABORT_INVALID_PATCH_EVT);
274             return;
275         }
276 
277 
278         /* Get info about the i2c patch*/
279         STREAM_TO_UINT8 (u8, p);                     /* power mode (not needed for i2c patch)    */
280         STREAM_TO_UINT16 (patchfile_patchsize, p);   /* size of patch                            */
281 
282         /* 5 byte RFU */
283         p += 5;
284 
285         /* Adjust length to exclude patchfiloe header */
286         nfc_hal_cb.prm.cur_patch_len_remaining -= (UINT16) (p - p_start);       /* Adjust size of patchfile                        */
287         nfc_hal_cb.prm.cur_patch_offset += (UINT16) (p - p_start);              /* Bytes of patchfile transmitted/processed so far */
288 
289         /* Begin sending patch to the NFCC */
290         nfc_hal_prm_spd_send_next_segment ();
291     }
292     else
293     {
294         /* ERROR: Bad length for patchfile */
295         NCI_TRACE_ERROR0 ("Invalid i2c fix: unexpected end of patch");
296         nfc_hal_prm_spd_handle_download_complete (NFC_HAL_PRM_ABORT_INVALID_PATCH_EVT);
297     }
298 }
299 #endif /* NFC_HAL_PRE_I2C_PATCH_INCLUDED */
300 
301 /*******************************************************************************
302 **
303 ** Function         nfc_hal_prm_spd_check_version
304 **
305 ** Description      Check patchfile version with current downloaded version
306 **
307 ** Returns          void
308 **
309 *******************************************************************************/
nfc_hal_prm_spd_check_version(void)310 void nfc_hal_prm_spd_check_version (void)
311 {
312     UINT8 *p, *p_start, i;
313     UINT32 patchfile_patch_present_mask;
314     UINT16 patchfile_project_id;
315     UINT16 patchfile_ver_major = 0;
316     UINT16 patchfile_ver_minor;
317     UINT16 patchfile_patchsize;
318 
319     UINT8  return_code = NFC_HAL_PRM_COMPLETE_EVT;
320 
321     /* Initialize patchfile offset pointers */
322     p = p_start = NULL;
323     patchfile_patchsize = 0;
324 
325     /* Get patchfile version */
326     if (nfc_hal_cb.prm.cur_patch_len_remaining >= NFC_HAL_PRM_NCD_PATCHFILE_HDR_LEN)
327     {
328         /* Parse patchfile header */
329         p       = (UINT8 *) nfc_hal_cb.prm.p_cur_patch_data;
330         p_start = p;
331         STREAM_TO_UINT16 (patchfile_project_id, p);
332         STREAM_TO_UINT16 (patchfile_ver_major, p);
333         STREAM_TO_UINT16 (patchfile_ver_minor, p);
334 
335         /* RFU */
336         p++;
337 
338         /* Check how many patches are in the patch file */
339         STREAM_TO_UINT8 (nfc_hal_cb.prm.spd_patch_count, p);
340 
341         if (nfc_hal_cb.prm.spd_patch_count > NFC_HAL_PRM_MAX_PATCH_COUNT)
342         {
343             NCI_TRACE_ERROR2 ("Unsupported patchfile (number of patches (%i) exceeds maximum (%i)",
344                                nfc_hal_cb.prm.spd_patch_count, NFC_HAL_PRM_MAX_PATCH_COUNT);
345         }
346 
347         /* Mask of patches that are present in the patchfile */
348         patchfile_patch_present_mask = 0;
349 
350         /* Get lengths for each patch */
351         for (i = 0; i < nfc_hal_cb.prm.spd_patch_count; i++)
352         {
353             /* Get power mode for this patch */
354             STREAM_TO_UINT8 (nfc_hal_cb.prm.spd_patch_desc[i].power_mode, p);
355 
356             /* Update mask of power-modes present in the patchfile */
357             patchfile_patch_present_mask |= ((UINT32) 1 << nfc_hal_cb.prm.spd_patch_desc[i].power_mode);
358 
359             /* Get length of patch */
360             STREAM_TO_UINT16 (nfc_hal_cb.prm.spd_patch_desc[i].len, p);
361 
362             /* Add total size of patches */
363             patchfile_patchsize += nfc_hal_cb.prm.spd_patch_desc[i].len;
364 
365             /* 5 byte RFU */
366             p += 5;
367         }
368 
369         /* Adjust offset to after the patch file header */
370         nfc_hal_cb.prm.cur_patch_offset += (UINT16) (p - p_start);              /* Bytes of patchfile transmitted/processed so far */
371         nfc_hal_cb.prm.cur_patch_len_remaining -= (UINT16) (p - p_start);       /* Adjust size of patchfile                        */
372 
373 
374         NCI_TRACE_DEBUG6 ("Patchfile info: ProjID=0x%04x,  Ver=%i.%i, Num patches=%i, PatchMask=0x%08x, PatchSize=%i",
375                            patchfile_project_id, patchfile_ver_major, patchfile_ver_minor,
376                            nfc_hal_cb.prm.spd_patch_count, patchfile_patch_present_mask, patchfile_patchsize);
377 
378         /*********************************************************************
379         * Version check of patchfile against NVM
380         *********************************************************************/
381 
382 #if (!defined (NFC_HAL_PRM_SKIP_VERSION_CHECK) || (NFC_HAL_PRM_SKIP_VERSION_CHECK == FALSE))
383         /* Download the patchfile if no patches in NVM */
384         if ((nfc_hal_cb.prm.spd_project_id == 0) || (nfc_hal_cb.prm.spd_nvm_patch_mask == 0))
385         {
386             /* No patch in NVM, need to download all */
387             nfc_hal_cb.prm.spd_patch_needed_mask = patchfile_patch_present_mask;
388 
389             NCI_TRACE_DEBUG2 ("No previous patch detected. Downloading patch %i.%i",
390                               patchfile_ver_major, patchfile_ver_minor);
391         }
392         /* Skip download if project ID of patchfile does not match NVM */
393         else if (nfc_hal_cb.prm.spd_project_id != patchfile_project_id)
394         {
395             /* Project IDs mismatch */
396             NCI_TRACE_DEBUG2 ("Patch download skipped: Mismatched Project ID (NVM ProjId: 0x%04x, Patchfile ProjId: 0x%04x)",
397                               nfc_hal_cb.prm.spd_project_id, patchfile_project_id);
398 
399             return_code = NFC_HAL_PRM_ABORT_INVALID_PATCH_EVT;
400         }
401         /* Skip download if version of patchfile older or equal to version in NVM */
402         /* unless NVM is corrupted (then don't skip download if patchfile has the same major ver)*/
403         else if (  (nfc_hal_cb.prm.spd_ver_major > patchfile_ver_major)
404                  ||(  (nfc_hal_cb.prm.spd_ver_major == patchfile_ver_major) && (nfc_hal_cb.prm.spd_ver_minor == patchfile_ver_minor)
405                     && !((patchfile_patch_present_mask & ( 1 << NFC_HAL_PRM_SPD_POWER_MODE_LPM)) && (nfc_hal_cb.prm.spd_lpm_patch_size == 0))  /* Do not skip download: patchfile has LPM, but NVM does not */
406                     && !((patchfile_patch_present_mask & ( 1 << NFC_HAL_PRM_SPD_POWER_MODE_FPM)) && (nfc_hal_cb.prm.spd_fpm_patch_size == 0))  /* Do not skip download: patchfile has FPM, but NVM does not */
407                     && !(nfc_hal_cb.prm.flags & (NFC_HAL_PRM_FLAGS_NVM_FPM_CORRUPTED |NFC_HAL_PRM_FLAGS_NVM_LPM_CORRUPTED))  )  )
408         {
409             /* NVM version is newer than patchfile */
410             NCI_TRACE_DEBUG2 ("Patch download skipped. NVM patch (version %i.%i) is newer than the patchfile ",
411                               nfc_hal_cb.prm.spd_ver_major, nfc_hal_cb.prm.spd_ver_minor);
412 
413             return_code = NFC_HAL_PRM_COMPLETE_EVT;
414         }
415         /* Remaining cases: patchfile major version is newer than NVM; or major version is the same with different minor version */
416         /* Download all patches in the patchfile */
417         else
418         {
419             nfc_hal_cb.prm.spd_patch_needed_mask = patchfile_patch_present_mask;
420 
421             NCI_TRACE_DEBUG4 ("Downloading patch version: %i.%i (previous version in NVM: %i.%i)...",
422                               patchfile_ver_major, patchfile_ver_minor,
423                               nfc_hal_cb.prm.spd_ver_major, nfc_hal_cb.prm.spd_ver_minor);
424         }
425 #else   /* NFC_HAL_PRM_SKIP_VERSION_CHECK */
426         nfc_hal_cb.prm.spd_patch_needed_mask = patchfile_patch_present_mask;
427 #endif
428     }
429     else
430     {
431         /* Invalid patch file header */
432         NCI_TRACE_ERROR0 ("Invalid patch file header.");
433 
434         return_code = NFC_HAL_PRM_ABORT_INVALID_PATCH_EVT;
435     }
436 
437     /* If we need to download anything, get the first patch to download */
438     if (nfc_hal_cb.prm.spd_patch_needed_mask)
439     {
440         NCI_TRACE_ERROR4 ("Downloading patch version: %i.%i (previous version in NVM: %i.%i)...",
441                             patchfile_ver_major, patchfile_ver_minor,
442                             nfc_hal_cb.prm.spd_ver_major, nfc_hal_cb.prm.spd_ver_minor);
443 #if (defined (NFC_HAL_PRE_I2C_PATCH_INCLUDED) && (NFC_HAL_PRE_I2C_PATCH_INCLUDED == TRUE))
444         /* Check if I2C patch is needed: if                                     */
445         /*      - I2C patch file was provided using HAL_NfcPrmSetI2cPatch, and        */
446         /*      -   current patch in NVM has ProjectID=0, or                    */
447         /*          FPM is not present or corrupted, or                         */
448         /*          or patchfile is major-ver 76+                               */
449         if (  (nfc_hal_cb.prm_i2c.p_patch)
450             &&(  (nfc_hal_cb.prm.spd_project_id == 0)
451                ||(nfc_hal_cb.prm.spd_fpm_patch_size == 0)
452                ||(nfc_hal_cb.prm.flags & NFC_HAL_PRM_FLAGS_NVM_FPM_CORRUPTED)
453                ||(patchfile_ver_major >= 76)))
454         {
455             NCI_TRACE_DEBUG0 ("I2C patch fix required.");
456             nfc_hal_cb.prm.flags |= NFC_HAL_PRM_FLAGS_I2C_FIX_REQUIRED;
457 
458             /* Download i2c fix first */
459             nfc_hal_prm_spd_download_i2c_fix ();
460             return;
461         }
462 #endif  /* NFC_HAL_PRE_I2C_PATCH_INCLUDED */
463 
464         /* Download first segment */
465         nfc_hal_cb.prm.state = NFC_HAL_PRM_ST_SPD_GET_PATCH_HEADER;
466         if (!(nfc_hal_cb.prm.flags & NFC_HAL_PRM_FLAGS_USE_PATCHRAM_BUF))
467         {
468             /* Notify adaptation layer to call HAL_NfcPrmDownloadContinue with the next patch segment */
469             (nfc_hal_cb.prm.p_cback) (NFC_HAL_PRM_SPD_GET_NEXT_PATCH);
470         }
471         else
472         {
473             nfc_hal_prm_spd_handle_next_patch_start ();
474         }
475     }
476     else
477     {
478         static BOOLEAN firstTime = TRUE;
479         if (firstTime) {
480             NCI_TRACE_ERROR2 ("BCM2079x: NVM patch version is %d.%d",
481                     nfc_hal_cb.prm.spd_ver_major, nfc_hal_cb.prm.spd_ver_minor);
482             firstTime = FALSE;
483         }
484         /* Download complete */
485         nfc_hal_prm_spd_handle_download_complete (return_code);
486     }
487 }
488 
489 #if (NFC_HAL_TRACE_VERBOSE == TRUE)
490 /*******************************************************************************
491 **
492 ** Function         nfc_hal_prm_spd_status_str
493 **
494 ** Description      Return status string for a given spd status code
495 **
496 ** Returns          Status string
497 **
498 *******************************************************************************/
nfc_hal_prm_spd_status_str(UINT8 spd_status_code)499 UINT8 *nfc_hal_prm_spd_status_str (UINT8 spd_status_code)
500 {
501     char *p_str;
502 
503     switch (spd_status_code)
504     {
505     case NCI_STATUS_SPD_ERROR_DEST:
506         p_str = "SPD_ERROR_DEST";
507         break;
508 
509     case NCI_STATUS_SPD_ERROR_PROJECTID:
510         p_str = "SPD_ERROR_PROJECTID";
511         break;
512 
513     case NCI_STATUS_SPD_ERROR_CHIPVER:
514         p_str = "SPD_ERROR_CHIPVER";
515         break;
516 
517     case NCI_STATUS_SPD_ERROR_MAJORVER:
518         p_str = "SPD_ERROR_MAJORVER";
519         break;
520 
521     case NCI_STATUS_SPD_ERROR_INVALID_PARAM:
522         p_str = "SPD_ERROR_INVALID_PARAM";
523         break;
524 
525     case NCI_STATUS_SPD_ERROR_INVALID_SIG:
526         p_str = "SPD_ERROR_INVALID_SIG";
527         break;
528 
529     case NCI_STATUS_SPD_ERROR_NVM_CORRUPTED:
530         p_str = "SPD_ERROR_NVM_CORRUPTED";
531         break;
532 
533     case NCI_STATUS_SPD_ERROR_PWR_MODE:
534         p_str = "SPD_ERROR_PWR_MODE";
535         break;
536 
537     case NCI_STATUS_SPD_ERROR_MSG_LEN:
538         p_str = "SPD_ERROR_MSG_LEN";
539         break;
540 
541     case NCI_STATUS_SPD_ERROR_PATCHSIZE:
542         p_str = "SPD_ERROR_PATCHSIZE";
543         break;
544 
545     default:
546         p_str = "Unspecified Error";
547         break;
548 
549     }
550 
551     return ((UINT8*) p_str);
552 }
553 #endif  /* (NFC_HAL_TRACE_VERBOSE == TRUE) */
554 
555 /*******************************************************************************
556 **
557 ** Function         nfc_hal_prm_nci_command_complete_cback
558 **
559 ** Description      Callback for NCI vendor specific command complete
560 **                  (for secure patch download)
561 **
562 ** Returns          void
563 **
564 *******************************************************************************/
nfc_hal_prm_nci_command_complete_cback(tNFC_HAL_NCI_EVT event,UINT16 data_len,UINT8 * p_data)565 void nfc_hal_prm_nci_command_complete_cback (tNFC_HAL_NCI_EVT event, UINT16 data_len, UINT8 *p_data)
566 {
567     UINT8 status, u8;
568     UINT8 *p;
569     UINT32 post_signature_delay;
570 
571     NFC_HAL_PRM_STATE ("nfc_hal_prm_nci_command_complete_cback");
572 
573     /* Stop the command-timeout timer */
574     nfc_hal_main_stop_quick_timer (&nfc_hal_cb.prm.timer);
575 
576     /* Skip over NCI header */
577     p = p_data + NCI_MSG_HDR_SIZE;
578 
579     /* Handle GET_PATCH_VERSION Rsp */
580     if (event == NFC_VS_GET_PATCH_VERSION_EVT)
581     {
582         /* Get project id */
583         STREAM_TO_UINT16 (nfc_hal_cb.prm.spd_project_id, p);
584 
585         /* RFU */
586         p++;
587 
588         /* Get chip version string */
589         STREAM_TO_UINT8 (u8, p);
590         p += NFC_HAL_PRM_NCD_PATCH_VERSION_LEN;
591 
592         /* Get major/minor version */
593         STREAM_TO_UINT16 (nfc_hal_cb.prm.spd_ver_major, p);
594         STREAM_TO_UINT16 (nfc_hal_cb.prm.spd_ver_minor, p);
595         STREAM_TO_UINT16 (nfc_hal_cb.prm.spd_nvm_max_size, p);
596         STREAM_TO_UINT16 (nfc_hal_cb.prm.spd_patch_max_size, p);
597         STREAM_TO_UINT16 (nfc_hal_cb.prm.spd_lpm_patch_size, p);
598         STREAM_TO_UINT16 (nfc_hal_cb.prm.spd_fpm_patch_size, p);
599 
600         /* LPMPatchCodeHasBadCRC (if not bad crc, then indicate LPM patch is present in nvm) */
601         STREAM_TO_UINT8 (u8, p);
602         if (!u8)
603         {
604             nfc_hal_cb.prm.spd_nvm_patch_mask |= (1 << NFC_HAL_PRM_SPD_POWER_MODE_LPM);
605         }
606         else
607         {
608             /* LPM patch in NVM fails CRC check */
609             nfc_hal_cb.prm.flags |= NFC_HAL_PRM_FLAGS_NVM_LPM_CORRUPTED;
610         }
611 
612 
613         /* FPMPatchCodeHasBadCRC (if not bad crc, then indicate LPM patch is present in nvm) */
614         STREAM_TO_UINT8 (u8, p);
615         if (!u8)
616         {
617             nfc_hal_cb.prm.spd_nvm_patch_mask |= (1 << NFC_HAL_PRM_SPD_POWER_MODE_FPM);
618         }
619         else
620         {
621             /* FPM patch in NVM fails CRC check */
622             nfc_hal_cb.prm.flags |= NFC_HAL_PRM_FLAGS_NVM_FPM_CORRUPTED;
623         }
624 
625         /* Check if downloading patch to RAM only (no NVM) */
626         STREAM_TO_UINT8 (u8, p);
627         if (!u8)
628         {
629             if (nfc_hal_prm_nvm_required)
630             {
631                 NCI_TRACE_ERROR0 ("This platform requires NVM and the NVM is not available - Abort");
632                 nfc_hal_prm_spd_handle_download_complete (NFC_HAL_PRM_ABORT_NO_NVM_EVT);
633                 return;
634             }
635             nfc_hal_cb.prm.flags |= NFC_HAL_PRM_FLAGS_NO_NVM;
636         }
637         /* Get patchfile version number */
638         nfc_hal_cb.prm.state = NFC_HAL_PRM_ST_SPD_COMPARE_VERSION;
639 
640         if (nfc_hal_cb.prm.flags & NFC_HAL_PRM_FLAGS_USE_PATCHRAM_BUF)
641         {
642             /* If patch is in a buffer, get patch version from buffer */
643             nfc_hal_prm_spd_check_version ();
644         }
645         else
646         {
647             /* Notify adaptation layer to send patch version (via HAL_NfcPrmDownloadContinue) */
648             (nfc_hal_cb.prm.p_cback) (NFC_HAL_PRM_SPD_GET_PATCHFILE_HDR_EVT);
649         }
650 
651     }
652     /* Handle SECURE_PATCH_DOWNLOAD Rsp */
653     else if (event == NFC_VS_SEC_PATCH_DOWNLOAD_EVT)
654     {
655         /* Status and error code */
656         STREAM_TO_UINT8 (status, p);
657         STREAM_TO_UINT8 (u8, p);
658 
659         if (status != NCI_STATUS_OK)
660         {
661 #if (NFC_HAL_TRACE_VERBOSE == TRUE)
662             NCI_TRACE_ERROR2 ("Patch download failed, reason code=0x%X (%s)", status, nfc_hal_prm_spd_status_str (status));
663 #else
664             NCI_TRACE_ERROR1 ("Patch download failed, reason code=0x%X", status);
665 #endif
666 
667             /* Notify application */
668             nfc_hal_prm_spd_handle_download_complete (NFC_HAL_PRM_ABORT_INVALID_PATCH_EVT);
669             return;
670         }
671 
672         /* If last segment (SIGNATURE) sent */
673         if (nfc_hal_cb.prm.flags & NFC_HAL_PRM_FLAGS_SIGNATURE_SENT)
674         {
675             /* Wait for authentication complate (SECURE_PATCH_DOWNLOAD NTF) */
676             nfc_hal_cb.prm.state = NFC_HAL_PRM_ST_SPD_AUTHENTICATING;
677             nfc_hal_main_start_quick_timer (&nfc_hal_cb.prm.timer, 0x00,
678                                             (NFC_HAL_PRM_SPD_TOUT * QUICK_TIMER_TICKS_PER_SEC) / 1000);
679             return;
680         }
681         /* Download next segment */
682         else if (nfc_hal_cb.prm.flags & NFC_HAL_PRM_FLAGS_USE_PATCHRAM_BUF)
683         {
684             /* If patch is in a buffer, get next patch from buffer */
685             nfc_hal_prm_spd_send_next_segment ();
686         }
687         else
688         {
689             /* Notify adaptation layer to get next patch segment (via HAL_NfcPrmDownloadContinue) */
690             (nfc_hal_cb.prm.p_cback) (NFC_HAL_PRM_CONTINUE_EVT);
691         }
692     }
693     /* Handle SECURE_PATCH_DOWNLOAD NTF */
694     else if (event == NFC_VS_SEC_PATCH_AUTH_EVT)
695     {
696         NCI_TRACE_DEBUG1 ("prm flags:0x%x.", nfc_hal_cb.prm.flags);
697         /* Status and error code */
698         STREAM_TO_UINT8 (status, p);
699         STREAM_TO_UINT8 (u8, p);
700 
701         /* Sanity check - should only get this NTF while in AUTHENTICATING stage */
702         if (nfc_hal_cb.prm.state == NFC_HAL_PRM_ST_SPD_AUTHENTICATING)
703         {
704             if (status != NCI_STATUS_OK)
705             {
706                 NCI_TRACE_ERROR0 ("Patch authentication failed");
707                 nfc_hal_prm_spd_handle_download_complete (NFC_HAL_PRM_ABORT_BAD_SIGNATURE_EVT);
708                 return;
709             }
710 
711 #if (defined (NFC_HAL_PRE_I2C_PATCH_INCLUDED) && (NFC_HAL_PRE_I2C_PATCH_INCLUDED == TRUE))
712             if (nfc_hal_cb.prm.flags & NFC_HAL_PRM_FLAGS_I2C_FIX_REQUIRED)
713             {
714                 NCI_TRACE_DEBUG1 ("PreI2C patch downloaded...waiting %i ms for NFCC to reboot.", nfc_hal_cb.prm_i2c.prei2c_delay);
715 
716                 /* Restore pointers to patchfile */
717                 nfc_hal_cb.prm.flags &= ~NFC_HAL_PRM_FLAGS_I2C_FIX_REQUIRED;
718                 nfc_hal_cb.prm.p_cur_patch_data = nfc_hal_cb.prm.p_spd_patch;
719                 nfc_hal_cb.prm.cur_patch_offset = nfc_hal_cb.prm.spd_patch_offset;
720                 nfc_hal_cb.prm.cur_patch_len_remaining = nfc_hal_cb.prm.spd_patch_len_remaining;
721 
722                 /* Resume normal patch download */
723                 nfc_hal_cb.prm.state = NFC_HAL_PRM_ST_SPD_GET_PATCH_HEADER;
724                 nfc_hal_cb.prm.flags &= ~NFC_HAL_PRM_FLAGS_SIGNATURE_SENT;
725 
726                 /* Post PreI2C delay */
727                 nfc_hal_main_start_quick_timer (&nfc_hal_cb.prm.timer, 0x00, (nfc_hal_cb.prm_i2c.prei2c_delay * QUICK_TIMER_TICKS_PER_SEC) / 1000);
728 
729                 return;
730             }
731 #endif  /* NFC_HAL_PRE_I2C_PATCH_INCLUDED */
732 
733 
734             /* Wait for NFCC to save the patch to NVM */
735             if (nfc_hal_cb.prm.flags & NFC_HAL_PRM_FLAGS_SUPPORT_RESET_NTF)
736             {
737                 /* 20791B4 or newer - wait for RESET_NTF */
738                 post_signature_delay = NFC_HAL_PRM_RESET_NTF_DELAY;
739                 NCI_TRACE_DEBUG1 ("Patch downloaded and authenticated. Waiting %i ms for RESET NTF...", post_signature_delay);
740 
741             }
742             else if (nfc_hal_cb.prm.flags & NFC_HAL_PRM_FLAGS_NO_NVM)
743             {
744                 /* No NVM. Wait for NFCC to restart */
745                 post_signature_delay = NFC_HAL_PRM_END_DELAY;
746                 NCI_TRACE_DEBUG1 ("Patch downloaded and authenticated. Waiting %i ms for NFCC to restart...", post_signature_delay);
747             }
748             else
749             {
750                 /* Wait for NFCC to save the patch to NVM (need about 1 ms per byte) */
751                 post_signature_delay = nfc_hal_cb.prm.spd_patch_desc[nfc_hal_cb.prm.spd_cur_patch_idx].len;
752                 if (post_signature_delay < nfc_hal_cb.prm.patchram_delay)
753                     post_signature_delay = nfc_hal_cb.prm.patchram_delay;
754                 NCI_TRACE_DEBUG1 ("Patch downloaded and authenticated. Waiting %i ms for NVM update to complete...", post_signature_delay);
755             }
756 
757             nfc_hal_cb.prm.state = NFC_HAL_PRM_ST_SPD_AUTH_DONE;
758 
759             nfc_hal_main_start_quick_timer (&nfc_hal_cb.prm.timer, 0x00,
760                                             (post_signature_delay * QUICK_TIMER_TICKS_PER_SEC) / 1000);
761         }
762         else
763         {
764             NCI_TRACE_ERROR0 ("Got unexpected SECURE_PATCH_DOWNLOAD NTF");
765             nfc_hal_prm_spd_handle_download_complete (NFC_HAL_PRM_ABORT_EVT);
766         }
767     }
768     else
769     {
770         /* Invalid response from NFCC during patch download */
771         NCI_TRACE_ERROR1 ("Invalid response from NFCC during patch download (opcode=0x%02X)", event);
772         nfc_hal_prm_spd_handle_download_complete (NFC_HAL_PRM_ABORT_INVALID_PATCH_EVT);
773     }
774 
775     NFC_HAL_PRM_STATE ("prm_nci_command_complete_cback");
776 }
777 
778 /*******************************************************************************
779 **
780 ** Function         nfc_hal_prm_nfcc_ready_to_continue
781 **
782 ** Description      Continue to download patch or notify application completition
783 **
784 ** Returns          void
785 **
786 *******************************************************************************/
nfc_hal_prm_nfcc_ready_to_continue(void)787 void nfc_hal_prm_nfcc_ready_to_continue (void)
788 {
789     /* Clear the bit for the patch we just downloaded */
790     nfc_hal_cb.prm.spd_patch_needed_mask &= ~ ((UINT32) 1 << nfc_hal_cb.prm.spd_patch_desc[nfc_hal_cb.prm.spd_cur_patch_idx].power_mode);
791 
792     /* Check if another patch to download */
793     nfc_hal_cb.prm.spd_cur_patch_idx++;
794     if ((nfc_hal_cb.prm.spd_patch_needed_mask) && (nfc_hal_cb.prm.spd_cur_patch_idx < nfc_hal_cb.prm.spd_patch_count))
795     {
796         nfc_hal_cb.prm.state = NFC_HAL_PRM_ST_SPD_GET_PATCH_HEADER;
797         nfc_hal_cb.prm.flags &= ~NFC_HAL_PRM_FLAGS_SIGNATURE_SENT;
798 
799         if (nfc_hal_cb.prm.flags & NFC_HAL_PRM_FLAGS_USE_PATCHRAM_BUF)
800         {
801             /* If patch is in a buffer, get next patch from buffer */
802             nfc_hal_prm_spd_handle_next_patch_start ();
803         }
804         else
805         {
806             /* Notify adaptation layer to get next patch header (via HAL_NfcPrmDownloadContinue) */
807             (nfc_hal_cb.prm.p_cback) (NFC_HAL_PRM_SPD_GET_NEXT_PATCH);
808         }
809 
810     }
811     else
812     {
813         /* Done downloading */
814         NCI_TRACE_DEBUG0 ("Patch downloaded and authenticated.");
815         nfc_hal_prm_spd_handle_download_complete (NFC_HAL_PRM_COMPLETE_EVT);
816     }
817 }
818 
819 /*******************************************************************************
820 **
821 ** Function         nfc_hal_prm_spd_reset_ntf
822 **
823 ** Description      Received RESET NTF from NFCC, indicating it has completed
824 **                  reset after patch download.
825 **
826 ** Returns          void
827 **
828 *******************************************************************************/
nfc_hal_prm_spd_reset_ntf(UINT8 reset_reason,UINT8 reset_type)829 void nfc_hal_prm_spd_reset_ntf (UINT8 reset_reason, UINT8 reset_type)
830 {
831     /* Check if we were expecting a RESET NTF */
832     if (nfc_hal_cb.prm.state == NFC_HAL_PRM_ST_SPD_AUTH_DONE)
833     {
834         NCI_TRACE_DEBUG2 ("Received RESET NTF after patch download (reset_reason=%i, reset_type=%i)", reset_reason, reset_type);
835 
836         /* Stop waiting for RESET NTF */
837         nfc_hal_main_stop_quick_timer (&nfc_hal_cb.prm.timer);
838 
839         {
840         /* Continue with patch download */
841         nfc_hal_prm_nfcc_ready_to_continue ();
842     }
843     }
844     else
845     {
846         NCI_TRACE_ERROR2 ("Received unexpected RESET NTF (reset_reason=%i, reset_type=%i)", reset_reason, reset_type);
847     }
848 }
849 
850 /*******************************************************************************
851 **
852 ** Function:    nfc_post_final_baud_update
853 **
854 ** Description: Called after baud rate udate
855 **
856 ** Returns:     Nothing
857 **
858 *******************************************************************************/
nfc_hal_prm_post_baud_update(tHAL_NFC_STATUS status)859 void nfc_hal_prm_post_baud_update (tHAL_NFC_STATUS status)
860 {
861     NFC_HAL_PRM_STATE ("nfc_hal_prm_post_baud_update");
862 
863     if (nfc_hal_cb.prm.state == NFC_HAL_PRM_ST_SPD_AUTH_DONE)
864     {
865         /* Proceed with next step of patch download sequence */
866         nfc_hal_prm_nfcc_ready_to_continue ();
867     }
868 }
869 
870 /*******************************************************************************
871 **
872 ** Function         nfc_hal_prm_process_timeout
873 **
874 ** Description      Process timer expireation for patch download
875 **
876 ** Returns          void
877 **
878 *******************************************************************************/
nfc_hal_prm_process_timeout(void * p_tle)879 void nfc_hal_prm_process_timeout (void *p_tle)
880 {
881     NFC_HAL_PRM_STATE ("nfc_hal_prm_process_timeout");
882 
883     if (nfc_hal_cb.prm.state == NFC_HAL_PRM_ST_IDLE)
884     {
885         nfc_hal_cb.prm.state = NFC_HAL_PRM_ST_SPD_GET_VERSION;
886 
887         /* Get currently downloaded patch version */
888         nfc_hal_dm_send_nci_cmd (nfc_hal_prm_get_patch_version_cmd, NCI_MSG_HDR_SIZE, nfc_hal_prm_nci_command_complete_cback);
889     }
890     else if (nfc_hal_cb.prm.state == NFC_HAL_PRM_ST_SPD_AUTH_DONE)
891     {
892         if (nfc_hal_cb.prm.flags & NFC_HAL_PRM_FLAGS_SUPPORT_RESET_NTF)
893         {
894             /* Timeout waiting for RESET NTF after signature sent */
895             NCI_TRACE_ERROR0 ("Timeout waiting for RESET NTF after patch download");
896             nfc_hal_prm_spd_handle_download_complete (NFC_HAL_PRM_ABORT_EVT);
897         }
898         else
899         {
900             nfc_hal_prm_nfcc_ready_to_continue ();
901         }
902     }
903     else if (nfc_hal_cb.prm.state == NFC_HAL_PRM_ST_SPD_GET_PATCH_HEADER)
904     {
905         NCI_TRACE_DEBUG0 ("Delay after PreI2C patch download...proceeding to download firmware patch");
906         nfc_hal_prm_spd_handle_next_patch_start ();
907     }
908     else
909     {
910         NCI_TRACE_ERROR1 ("Patch download: command timeout (state=%i)", nfc_hal_cb.prm.state);
911 
912         nfc_hal_prm_spd_handle_download_complete (NFC_HAL_PRM_ABORT_EVT);
913     }
914 
915     NFC_HAL_PRM_STATE ("nfc_hal_prm_process_timeout");
916 }
917 
918 
919 /*******************************************************************************
920 **
921 ** Function         HAL_NfcPrmDownloadStart
922 **
923 ** Description      Initiate patch download
924 **
925 ** Input Params
926 **                  format_type     patch format type
927 **                                  (NFC_HAL_PRM_FORMAT_BIN, NFC_HAL_PRM_FORMAT_HCD, or
928 **                                   NFC_HAL_PRM_FORMAT_NCD)
929 **
930 **                  dest_address    destination adderess (needed for BIN format only)
931 **
932 **                  p_patchram_buf  pointer to patchram buffer. If NULL,
933 **                                  then app must call HAL_NfcPrmDownloadContinue when
934 **                                  NFC_HAL_PRM_CONTINUE_EVT is received, to send the next
935 **                                  segment of patchram
936 **
937 **                  patchram_len    size of p_patchram_buf (if non-NULL)
938 **
939 **                  patchram_delay  The delay after each patch.
940 **                                  If the given value is less than the size of the patchram,
941 **                                  the size of patchram is used instead.
942 **
943 **                  p_cback         callback for download status
944 **
945 **
946 ** Returns          TRUE if successful, otherwise FALSE
947 **
948 **
949 *******************************************************************************/
HAL_NfcPrmDownloadStart(tNFC_HAL_PRM_FORMAT format_type,UINT32 dest_address,UINT8 * p_patchram_buf,UINT32 patchram_len,UINT32 patchram_delay,tNFC_HAL_PRM_CBACK * p_cback)950 BOOLEAN HAL_NfcPrmDownloadStart (tNFC_HAL_PRM_FORMAT format_type,
951                                  UINT32              dest_address,
952                                  UINT8               *p_patchram_buf,
953                                  UINT32              patchram_len,
954                                  UINT32              patchram_delay,
955                                  tNFC_HAL_PRM_CBACK  *p_cback)
956 {
957     NCI_TRACE_API0 ("HAL_NfcPrmDownloadStart ()");
958 
959     memset (&nfc_hal_cb.prm, 0, sizeof (tNFC_HAL_PRM_CB));
960 
961     if (p_patchram_buf)
962     {
963         nfc_hal_cb.prm.p_cur_patch_data = p_patchram_buf;
964         nfc_hal_cb.prm.cur_patch_offset = 0;
965         nfc_hal_cb.prm.cur_patch_len_remaining = (UINT16) patchram_len;
966         nfc_hal_cb.prm.flags |= NFC_HAL_PRM_FLAGS_USE_PATCHRAM_BUF;
967 
968         if (patchram_len == 0)
969             return FALSE;
970     }
971 
972     nfc_hal_cb.prm.p_cback          = p_cback;
973     nfc_hal_cb.prm.dest_ram         = dest_address;
974     nfc_hal_cb.prm.format           = format_type;
975     nfc_hal_cb.prm.patchram_delay   = patchram_delay;
976 
977     nfc_hal_cb.prm.timer.p_cback = nfc_hal_prm_process_timeout;
978 
979     if (format_type == NFC_HAL_PRM_FORMAT_NCD)
980     {
981         /* Store patch buffer pointer and length */
982         nfc_hal_cb.prm.p_spd_patch             = p_patchram_buf;
983         nfc_hal_cb.prm.spd_patch_len_remaining = (UINT16)patchram_len;
984         nfc_hal_cb.prm.spd_patch_offset        = 0;
985 
986         /* Need delay for controller to finish resetting */
987         nfc_hal_main_start_quick_timer (&nfc_hal_cb.prm.timer, 0x00,
988                                         (NFC_HAL_PRM_SPD_PRE_DOWNLOAD_DELAY * QUICK_TIMER_TICKS_PER_SEC) / 1000);
989     }
990     else
991     {
992         NCI_TRACE_ERROR0 ("Unexpected patch format.");
993         return FALSE;
994     }
995 
996     return TRUE;
997 }
998 
999 /*******************************************************************************
1000 **
1001 ** Function         HAL_NfcPrmDownloadContinue
1002 **
1003 ** Description      Send next segment of patchram to controller. Called when
1004 **                  NFC_HAL_PRM_CONTINUE_EVT is received.
1005 **
1006 **                  Only needed if HAL_NfcPrmDownloadStart was called with
1007 **                  p_patchram_buf=NULL
1008 **
1009 ** Input Params     p_patch_data    pointer to patch data
1010 **                  patch_data_len  patch data len
1011 **
1012 ** Returns          TRUE if successful, otherwise FALSE
1013 **
1014 *******************************************************************************/
HAL_NfcPrmDownloadContinue(UINT8 * p_patch_data,UINT16 patch_data_len)1015 BOOLEAN HAL_NfcPrmDownloadContinue (UINT8 *p_patch_data,
1016                                     UINT16 patch_data_len)
1017 {
1018     NCI_TRACE_API2 ("HAL_NfcPrmDownloadContinue ():state = %d, patch_data_len=%d",
1019                      nfc_hal_cb.prm.state, patch_data_len);
1020 
1021     /* Check if we are in a valid state for this API */
1022     if (  (nfc_hal_cb.prm.state != NFC_HAL_PRM_ST_SPD_COMPARE_VERSION)
1023         &&(nfc_hal_cb.prm.state != NFC_HAL_PRM_ST_SPD_GET_PATCH_HEADER)
1024         &&(nfc_hal_cb.prm.state != NFC_HAL_PRM_ST_SPD_DOWNLOADING)  )
1025         return FALSE;
1026 
1027     if (patch_data_len == 0)
1028         return FALSE;
1029 
1030     nfc_hal_cb.prm.cur_patch_offset = 0;
1031     nfc_hal_cb.prm.p_cur_patch_data = p_patch_data;
1032     nfc_hal_cb.prm.cur_patch_len_remaining = patch_data_len;
1033 
1034     /* Call appropriate handler */
1035     if (nfc_hal_cb.prm.state == NFC_HAL_PRM_ST_SPD_COMPARE_VERSION)
1036     {
1037         nfc_hal_prm_spd_check_version ();
1038     }
1039     else if (nfc_hal_cb.prm.state == NFC_HAL_PRM_ST_SPD_GET_PATCH_HEADER)
1040     {
1041         nfc_hal_prm_spd_handle_next_patch_start ();
1042     }
1043     else if (nfc_hal_cb.prm.state == NFC_HAL_PRM_ST_SPD_DOWNLOADING)
1044     {
1045         nfc_hal_prm_spd_send_next_segment ();
1046     }
1047     else
1048     {
1049         NCI_TRACE_ERROR1 ("Unexpected patch state:%d.", nfc_hal_cb.prm.state);
1050     }
1051 
1052     return TRUE;
1053 }
1054 
1055 /*******************************************************************************
1056 **
1057 ** Function         HAL_NfcPrmSetI2cPatch
1058 **
1059 ** Description      Specify patchfile for BCM20791B3 I2C fix. This fix
1060 **                  must be downloaded prior to initial patch download for I2C
1061 **                  transport
1062 **
1063 ** Input Params     p_i2c_patchfile_buf: pointer to patch for i2c fix
1064 **                  i2c_patchfile_len: length of patch
1065 **                  prei2c_delay: the delay before downloading main patch
1066 **                                if 0 is given, NFC_HAL_PRM_POST_I2C_FIX_DELAY is used instead.
1067 **
1068 ** Returns          Nothing
1069 **
1070 **
1071 *******************************************************************************/
HAL_NfcPrmSetI2cPatch(UINT8 * p_i2c_patchfile_buf,UINT16 i2c_patchfile_len,UINT32 prei2c_delay)1072 void HAL_NfcPrmSetI2cPatch (UINT8 *p_i2c_patchfile_buf, UINT16 i2c_patchfile_len, UINT32 prei2c_delay)
1073 {
1074 #if (defined (NFC_HAL_PRE_I2C_PATCH_INCLUDED) && (NFC_HAL_PRE_I2C_PATCH_INCLUDED == TRUE))
1075     NCI_TRACE_API0 ("HAL_NfcPrmSetI2cPatch ()");
1076 
1077     nfc_hal_cb.prm_i2c.prei2c_delay    = NFC_HAL_PRM_POST_I2C_FIX_DELAY;
1078     if (prei2c_delay)
1079         nfc_hal_cb.prm_i2c.prei2c_delay = prei2c_delay;
1080     nfc_hal_cb.prm_i2c.p_patch = p_i2c_patchfile_buf;
1081     nfc_hal_cb.prm_i2c.len = i2c_patchfile_len;
1082 #endif  /* NFC_HAL_PRE_I2C_PATCH_INCLUDED */
1083 }
1084 
1085 /*******************************************************************************
1086 **
1087 ** Function         HAL_NfcPrmSetSpdNciCmdPayloadSize
1088 **
1089 ** Description      Set Host-to-NFCC NCI message size for secure patch download
1090 **
1091 **                  This API must be called before calling HAL_NfcPrmDownloadStart.
1092 **                  If the API is not called, then PRM will use the default
1093 **                  message size.
1094 **
1095 **                  Typically, this API is only called for platforms that have
1096 **                  message-size limitations in the transport/driver.
1097 **
1098 **                  Valid message size range: NFC_HAL_PRM_MIN_NCI_CMD_PAYLOAD_SIZE to 255.
1099 **
1100 ** Returns          HAL_NFC_STATUS_OK if successful
1101 **                  HAL_NFC_STATUS_FAILED otherwise
1102 **
1103 **
1104 *******************************************************************************/
HAL_NfcPrmSetSpdNciCmdPayloadSize(UINT8 max_payload_size)1105 tHAL_NFC_STATUS HAL_NfcPrmSetSpdNciCmdPayloadSize (UINT8 max_payload_size)
1106 {
1107     /* Validate: minimum size is NFC_HAL_PRM_MIN_NCI_CMD_PAYLOAD_SIZE */
1108     if (max_payload_size < NFC_HAL_PRM_MIN_NCI_CMD_PAYLOAD_SIZE)
1109     {
1110         NCI_TRACE_ERROR2 ("HAL_NfcPrmSetSpdNciCmdPayloadSize: invalid size (%i). Must be between %i and 255", max_payload_size, NFC_HAL_PRM_MIN_NCI_CMD_PAYLOAD_SIZE);
1111         return (HAL_NFC_STATUS_FAILED);
1112     }
1113     else
1114     {
1115         NCI_TRACE_API1 ("HAL_NfcPrmSetSpdNciCmdPayloadSize: new message size during download: %i", max_payload_size);
1116         nfc_hal_cb.ncit_cb.nci_ctrl_size = max_payload_size;
1117         return (HAL_NFC_STATUS_OK);
1118     }
1119 }
1120