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