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