• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2021-2023 NXP
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include <sys/ioctl.h>
18 #include <dlfcn.h>
19 
20 #include "fwd_hdll.h"
21 #include "phNxpConfig.h"
22 #include "phNxpLog.h"
23 #include "phNxpUciHal_fwd_utils.h"
24 #include "phNxpUciHal_utils.h"
25 #include "phTmlUwb_spi.h"
26 
27 #define MAX_FRAME_LEN 4200
28 static uint8_t is_fw_download_log_enabled = 0x00;
29 
30 static phFWD_Status_t openFwBinFile(phUwbFWImageContext_t *pfwImageCtx);
31 static phFWD_Status_t openFwSoFile(phUwbFWImageContext_t *pfwImageCtx);
32 static phFWD_Status_t phNxpUciHal_fw_recovery(phUwbFWImageContext_t *pfwImageCtx);
33 
34 char default_fw_path[FILEPATH_MAXLEN] = "/vendor/firmware/uwb/";
35 const char *default_dev_fw_bin = "libsr200t_fw.bin";
36 const char *default_dev_fw_so = "libsr200t_fw.so";
37 const char *default_so_file_extn = ".so";
38 extern uint32_t timeoutTimerId;
39 static bool isHdllReadTmeoutExpired = false;
40 static bool bSkipEdlCheck = false;
41 static bool glcRotation = false;
42 
43 phUwbFWImageContext_t fwImageCtx;
44 
45 /*******************************************************************************
46 **
47 ** Function    :   phGenericSendAndRecv
48 **
49 ** Description :   This function sends the HDLL commands to HeliosX chip over
50                    SPI using phHdll_PutApdu() and gets the response using
51                    phHdll_GetApdu().
52 **
53 ** Parameters  :   payload     - HDLL command to be sent
54                    len         - HDLL command length
55                    readbuff    - HDLL command response buffer
56                    rsp_buf_len - HDLL command rsponse buffer length
57 **
58 ** Returns     :   phFWD_Status_t : 0 - success
59                                      1 - failure
60 **
61 **
62 *******************************************************************************/
phGenericSendAndRecv(uint8_t * payload,uint16_t len,uint8_t * read_buff,uint16_t * rsp_buf_len)63 phFWD_Status_t phGenericSendAndRecv(uint8_t *payload, uint16_t len,
64                                     uint8_t *read_buff, uint16_t *rsp_buf_len) {
65   phFWD_Status_t ret = FW_DNLD_FAILURE;
66   if (FW_DNLD_SUCCESS != (ret = phHdll_PutApdu((uint8_t *)&payload[0], len))) {
67     return ret;
68   }
69   if (FW_DNLD_SUCCESS !=
70       (ret = phHdll_GetApdu((uint8_t *)&read_buff[0], HDLL_READ_BUFF_SIZE,
71                             rsp_buf_len))) {
72     return ret;
73   }
74   return ret;
75 }
76 
77 /*******************************************************************************
78 **
79 ** Function    :   print_getInfoRsp
80 **
81 ** Description :   This function prints the HDLL GetInfo command's response
82 **
83 ** Parameters  :   getInfoRsp  - Struct which has the GetInfo response details.
84 **
85 ** Returns     :   None
86 **
87 **
88 *******************************************************************************/
print_getInfoRsp(phHDLLGetInfo_t * getInfoRsp)89 void print_getInfoRsp(phHDLLGetInfo_t *getInfoRsp) {
90   uint8_t i = 0, offset = 0;
91   char buff[HDLL_READ_BUFF_SIZE] = {0};
92   if (NULL == getInfoRsp) {
93     return;
94   }
95   NXPLOG_FWDNLD_D("=====================GET_INFO =======================\n");
96   NXPLOG_FWDNLD_D("Boot Status: 0x%02X\n", getInfoRsp->boot_status);
97   NXPLOG_FWDNLD_D("Session Control: 0x%02X\n", getInfoRsp->session_control);
98   NXPLOG_FWDNLD_D("Session Type: 0x%02X\n", getInfoRsp->session_type);
99   NXPLOG_FWDNLD_D("ROM Version: 0x%02X\n", getInfoRsp->rom_version);
100   NXPLOG_FWDNLD_D("AT Page Status: 0x%02X\n", getInfoRsp->AT_page_status);
101   NXPLOG_FWDNLD_D("Chip Version: Major.Minor: %02X.%02X\n",
102                   getInfoRsp->chip_major_ver, getInfoRsp->chip_minor_ver);
103   NXPLOG_FWDNLD_D("FW Version: Major.Minor: %02X.%02X\n",
104                   getInfoRsp->fw_major_ver, getInfoRsp->fw_minor_ver);
105 
106   for (i = 0; i != 8; i += 2) { // 4bytes
107     sprintf(&buff[i], "%02X", getInfoRsp->chip_variant[offset++]);
108   }
109   buff[i] = '\0';
110   NXPLOG_FWDNLD_D("Chip Variant: 0x%s\n", buff);
111   NXPLOG_FWDNLD_D("Device Lifecycle: 0x%X\n", getInfoRsp->device_life_cycle);
112 
113   for (i = 0, offset = 0; i != 32; i += 2) { // 16bytes
114     sprintf(&buff[i], "%02X", getInfoRsp->chip_id[offset++]);
115   }
116   buff[i] = '\0';
117   NXPLOG_FWDNLD_D("Chip ID: 0x%s\n", buff);
118 
119   for (i = 0, offset = 0; i != 8; i += 2) { // 4bytes
120     sprintf(&buff[i], "%02X", getInfoRsp->chip_id_crc[offset++]);
121   }
122   buff[i] = '\0';
123   NXPLOG_FWDNLD_D("Chip ID CRC:0x%s\n", buff);
124   NXPLOG_FWDNLD_D("=====================================================\n");
125 }
126 
127 /*******************************************************************************
128 **
129 ** Function    :   process_getInfo_rsp
130 **
131 ** Description :   This function processes the HDLL GetInfo command's response
132 **
133 ** Parameters  :   payload  - Struct in which the processed info will be kept
134 **
135 ** Returns     :   On failure - NULL
136                    On success - Pointer to the phHDLLGetInfo_t struct
137 **
138 **
139 *******************************************************************************/
process_getInfo_rsp(uint8_t * payload)140 phHDLLGetInfo_t *process_getInfo_rsp(uint8_t *payload) {
141   uint8_t offset = 0;
142   phHDLLGetInfo_t *getInfoRsp = NULL;
143   uint8_t device_lc_mode[4] = {0};
144 
145   getInfoRsp = (phHDLLGetInfo_t *)malloc(sizeof(phHDLLGetInfo_t));
146   if (NULL == getInfoRsp) {
147     return NULL;
148   }
149   memset(getInfoRsp, 0, sizeof(phHDLLGetInfo_t));
150   getInfoRsp->boot_status = payload[offset++];
151   getInfoRsp->session_control = payload[offset++];
152   getInfoRsp->session_type = payload[offset++];
153   getInfoRsp->rom_version = (eUWBD_Rom_Version_t)payload[offset++];
154   getInfoRsp->AT_page_status = (eUWBD_AT_Page_status_t)payload[offset++];
155   offset += 2; // padding bytes
156   getInfoRsp->chip_major_ver = payload[offset++];
157   getInfoRsp->chip_minor_ver = payload[offset++];
158   getInfoRsp->fw_major_ver = payload[offset++];
159   getInfoRsp->fw_minor_ver = payload[offset++];
160   memcpy(getInfoRsp->chip_variant, payload + offset, sizeof(uint8_t) * 4);
161   offset += 4;
162   memcpy(device_lc_mode, payload + offset, sizeof(uint8_t) * 4);
163   getInfoRsp->device_life_cycle = (eUWBD_LC_mode_t)(device_lc_mode[0] | (device_lc_mode[1] << 8) | (device_lc_mode[2] << 16) | (device_lc_mode[3] << 24));
164   offset += 4;
165   memcpy(getInfoRsp->chip_id, payload + offset, sizeof(uint8_t) * 16);
166   offset += 16;
167   memcpy(getInfoRsp->chip_id_crc, payload + offset, sizeof(uint8_t) * 4);
168   return getInfoRsp;
169 }
170 
171 /*******************************************************************************
172 **
173 ** Function    :   getFwImageCtx
174 **
175 ** Description :   This function use to get the FW image context
176 **
177 ** Parameters  :   pfwImageCtx -> pointer to fw image context
178 **
179 ** Returns     :   On failure - returns FW_DNLD_FAILURE
180                               - or FW_DNLD_FILE_NOT_FOUND if FW file not present
181                                 in the MW.
182                    On success - returns FW_DNLD_SUCCESS.
183 **
184 **
185 *******************************************************************************/
getFwImageCtx(phUwbFWImageContext_t * pfwImageCtx)186 phFWD_Status_t getFwImageCtx(phUwbFWImageContext_t *pfwImageCtx) {
187   phFWD_Status_t status = FW_DNLD_SUCCESS;
188   char *configured_fw_name = NULL;
189   const uint16_t fw_file_max_len = FILENAME_MAXLEN;
190   const char *pDefaultFwFileName = NULL;
191   char* ret = NULL;
192 
193   configured_fw_name = (char *)malloc(fw_file_max_len * sizeof(char));
194   int maxSrcLen = (FILEPATH_MAXLEN - strlen(pfwImageCtx->default_fw_path)) - 1;
195   if (configured_fw_name == NULL) {
196     NXPLOG_FWDNLD_E("malloc of configured_fw_name failed ");
197     return FW_DNLD_FAILURE;
198   }
199 
200   /* Default FW download configset to bin file */
201   pDefaultFwFileName = default_dev_fw_bin;
202 
203   if (!NxpConfig_GetStr(NAME_NXP_UWB_FW_FILENAME, configured_fw_name,
204                             fw_file_max_len)) {
205     NXPLOG_FWDNLD_D("Invalid Dev Fw  name keeping the default name: %s",
206                     pDefaultFwFileName);
207     strncat(pfwImageCtx->default_fw_path, pDefaultFwFileName, maxSrcLen);
208   } else {
209     NXPLOG_FWDNLD_D("configured_fw_name : %s", configured_fw_name);
210     strncat(pfwImageCtx->default_fw_path, configured_fw_name, maxSrcLen);
211   }
212 
213   NXPLOG_FWDNLD_D("fw file path : %s", pfwImageCtx->default_fw_path);
214   // Search for so extension in filename
215   ret = strstr(configured_fw_name, default_so_file_extn);
216   if(ret) {
217     pfwImageCtx->fw_dnld_config = SO_FILE_BASED_FW_DOWNLOAD;
218     /* Get Fw Context from so file */
219     status = openFwSoFile(pfwImageCtx);
220   } else {
221     /* Get Fw Context from bin file */
222     status = openFwBinFile(pfwImageCtx);
223   }
224 
225   if (configured_fw_name != NULL) {
226       free(configured_fw_name);
227     }
228   memset(pfwImageCtx->default_fw_path, '\0', sizeof(char) * FILEPATH_MAXLEN);
229   strcpy(pfwImageCtx->default_fw_path, "/vendor/firmware/uwb/");
230   return status;
231 }
232 
233 /*******************************************************************************
234 **
235 ** Function    :   printManifestInfo
236 **
237 ** Description :   This function is use to get UWB Manifest info
238 **
239 ** Parameters  :   pfwImageCtx -> pointer to fw image context
240 **
241 ** Returns     :   On failure - returns FW_DNLD_FAILURE
242                               - or FW_DNLD_FILE_NOT_FOUND if FW file not present
243                                 in the MW.
244                    On success - returns FW_DNLD_SUCCESS.
245 **
246 **
247 *******************************************************************************/
printManifest_info(UWBManifest_t * fwLibManifest)248 void printManifest_info(UWBManifest_t *fwLibManifest) {
249 
250   if(fwLibManifest == NULL) {
251     return;
252   }
253   NXPLOG_FWDNLD_D("================= FW Lib Manifest ====================\n");
254   NXPLOG_FWDNLD_D("UWB manifest version = %x\n",fwLibManifest->layout_version);
255   NXPLOG_FWDNLD_D("UWB manifest creation year = %d\n",fwLibManifest->creation_date_yy);
256   NXPLOG_FWDNLD_D("UWB manifest creation month = %d\n",fwLibManifest->creation_date_month);
257   NXPLOG_FWDNLD_D("UWB manifest creation day = %d\n",fwLibManifest->creation_date_day);
258   NXPLOG_FWDNLD_D("UWB manifest creation hour = %d\n",fwLibManifest->creation_date_hour);
259   NXPLOG_FWDNLD_D("UWB manifest creation minutes = %d\n",fwLibManifest->creation_date_minutes);
260   NXPLOG_FWDNLD_D("UWB manifest creation seconds = %d\n",fwLibManifest->creation_date_seconds);
261   NXPLOG_FWDNLD_D("UWB manifest count  = %d\n",fwLibManifest->countMWCESFW);
262 
263   return;
264 
265 }
266 
267 /*******************************************************************************
268 **
269 ** Function    :   openFwSoFile
270 **
271 ** Description :   This function loads the FW shared library context
272                    if the FW file exists otherwise returns failure.
273 **
274 ** Parameters  :   pfwImageCtx -> pointer to fw image context
275 **
276 ** Returns     :   On failure - returns FW_DNLD_FAILURE
277                               - or FW_DNLD_FILE_NOT_FOUND if FW file not present
278                                 in the MW.
279                    On success - returns FW_DNLD_SUCCESS.
280 **
281 **
282 *******************************************************************************/
openFwSoFile(phUwbFWImageContext_t * pfwImageCtx)283 static phFWD_Status_t openFwSoFile(phUwbFWImageContext_t *pfwImageCtx) {
284   void *flibptr = NULL;
285   UWBManifest_t *currentFwLib = NULL;
286   pfwImageCtx->gFwLib = NULL;
287   phFWD_Status_t status = FW_DNLD_SUCCESS;
288 
289   NXPLOG_FWDNLD_D("%s:%d enter", __func__,__LINE__);
290 
291   pfwImageCtx->gFwLib = dlopen(pfwImageCtx->default_fw_path, RTLD_LAZY);
292   if (pfwImageCtx->gFwLib == NULL) {
293     // Apparently, the library could not be opened
294     NXPLOG_FWDNLD_E("%s: Error! opening FW file %s\n", __func__,
295                     pfwImageCtx->default_fw_path);
296     status = FW_DNLD_FILE_NOT_FOUND;
297     goto cleanup;
298   }
299   flibptr = dlsym(pfwImageCtx->gFwLib, "gUWBManifest");
300   if (!flibptr) {
301     NXPLOG_FWDNLD_E("%s: Could not get function pointer\n", __func__);
302     status = FW_DNLD_FAILURE;
303     goto cleanup;
304   }
305 
306   currentFwLib = (UWBManifest_t *)flibptr;
307   if (currentFwLib == NULL) {
308     NXPLOG_FWDNLD_E("%s:%d UwbManifest is null exiting.....", __func__, __LINE__);
309     status = FW_DNLD_FAILURE;
310     goto cleanup;
311   }
312 
313   printManifest_info(currentFwLib);
314 
315   // read the FW bytes into buffer
316   if (pfwImageCtx->deviceInfo->rom_version == VER_A1V1) {
317     if(currentFwLib->mwCESFW[MWCESFW_A1V1_RECOVERY_FW_OFFSET] == NULL || currentFwLib->mwCESFW[MWCESFW_A1V1_FW_OFFSET] == NULL) {
318         NXPLOG_FWDNLD_E("%s:%d UwbManifest mwCESFW is null exiting.....", __func__, __LINE__);
319         status = FW_DNLD_FAILURE;
320         goto cleanup;
321     }
322     if(pfwImageCtx->deviceInfo->AT_page_status == STATUS_PAGE_ERROR) {
323       pfwImageCtx->fwRecovery = true;
324       pfwImageCtx->fwImgSize = currentFwLib->mwCESFW[MWCESFW_A1V1_RECOVERY_FW_OFFSET]->lenCESFW;
325       pfwImageCtx->fwImage = currentFwLib->mwCESFW[MWCESFW_A1V1_RECOVERY_FW_OFFSET]->pCESFW;
326     } else if((pfwImageCtx->deviceInfo->device_life_cycle == CUSTOMER_MODE) && glcRotation == true) {
327       if(currentFwLib->mwCESFW[MWCESFW_A1V1_LC_FW_OFFSET] == NULL ) {
328         NXPLOG_FWDNLD_E("%s:%d LC FW does not exist.....", __func__, __LINE__);
329         status = FW_DNLD_FAILURE;
330         goto cleanup;
331       } else {
332         pfwImageCtx->fwImgSize = currentFwLib->mwCESFW[MWCESFW_A1V1_LC_FW_OFFSET]->lenCESFW;
333         pfwImageCtx->fwImage = currentFwLib->mwCESFW[MWCESFW_A1V1_LC_FW_OFFSET]->pCESFW;
334       }
335     }else {
336       pfwImageCtx->fwImgSize = currentFwLib->mwCESFW[MWCESFW_A1V1_FW_OFFSET]->lenCESFW;
337       pfwImageCtx->fwImage = currentFwLib->mwCESFW[MWCESFW_A1V1_FW_OFFSET]->pCESFW;
338     }
339   }
340   else if (pfwImageCtx->deviceInfo->rom_version == VER_A1V2) {
341     if(currentFwLib->mwCESFW[MWCESFW_A1V2_RECOVERY_FW_OFFSET] == NULL || currentFwLib->mwCESFW[MWCESFW_A1V2_FW_OFFSET] == NULL) {
342         NXPLOG_FWDNLD_E("%s:%d UwbManifest mwCESFW is null exiting.....", __func__, __LINE__);
343         status = FW_DNLD_FAILURE;
344         goto cleanup;
345     }
346     if(pfwImageCtx->deviceInfo->AT_page_status == STATUS_PAGE_ERROR) {
347       pfwImageCtx->fwRecovery = true;
348       pfwImageCtx->fwImgSize = currentFwLib->mwCESFW[MWCESFW_A1V2_RECOVERY_FW_OFFSET]->lenCESFW;
349       pfwImageCtx->fwImage = currentFwLib->mwCESFW[MWCESFW_A1V2_RECOVERY_FW_OFFSET]->pCESFW;
350     } else if((pfwImageCtx->deviceInfo->device_life_cycle == CUSTOMER_MODE) && glcRotation == true) {
351       if(currentFwLib->mwCESFW[MWCESFW_A1V2_LC_FW_OFFSET] == NULL ) {
352         NXPLOG_FWDNLD_E("%s:%d LC FW does not exist.....", __func__, __LINE__);
353         status = FW_DNLD_FAILURE;
354         goto cleanup;
355       } else {
356         pfwImageCtx->fwImgSize = currentFwLib->mwCESFW[MWCESFW_A1V2_LC_FW_OFFSET]->lenCESFW;
357         pfwImageCtx->fwImage = currentFwLib->mwCESFW[MWCESFW_A1V2_LC_FW_OFFSET]->pCESFW;
358       }
359     } else {
360       pfwImageCtx->fwImgSize = currentFwLib->mwCESFW[MWCESFW_A1V2_FW_OFFSET]->lenCESFW;
361       pfwImageCtx->fwImage = currentFwLib->mwCESFW[MWCESFW_A1V2_FW_OFFSET]->pCESFW;
362     }
363   }
364   if ((!(pfwImageCtx->fwImgSize)) || (NULL == pfwImageCtx->fwImage)) {
365     NXPLOG_FWDNLD_E("%s: Error! File %s is empty\n", __func__, pfwImageCtx->default_fw_path);
366     status = FW_DNLD_FAILURE;
367     goto cleanup;
368   }
369 
370   NXPLOG_FWDNLD_E("exiting %s fwImgSize %d" , __func__, pfwImageCtx->fwImgSize);
371 
372   return status;
373 
374 cleanup:
375   if (pfwImageCtx->gFwLib != NULL) {
376         dlclose(pfwImageCtx->gFwLib);
377         pfwImageCtx->gFwLib = NULL;
378   }
379   return status;
380 
381 }
382 
383 /*******************************************************************************
384 **
385 ** Function    :   openFwBinFile
386 **
387 ** Description :   This function copies the entire Bin FW file content into a buffer
388                    if the FW file exists otherwise returns failure.
389 **
390 ** Parameters  :   pfwImageCtx -> pointer to fw image context
391 **
392 ** Returns     :   On failure - returns FW_DNLD_FAILURE
393                               - or FW_DNLD_FILE_NOT_FOUND if FW file not present
394                                 in the MW.
395                    On success - returns FW_DNLD_SUCCESS.
396 **
397 **
398 *******************************************************************************/
openFwBinFile(phUwbFWImageContext_t * pfwImageCtx)399 static phFWD_Status_t openFwBinFile(phUwbFWImageContext_t *pfwImageCtx) {
400   phFWD_Status_t status = FW_DNLD_SUCCESS;
401   long int file_size = 0;
402   size_t ret_size = 0;
403   FILE *fptr = NULL;
404 
405   NXPLOG_FWDNLD_D("%s:%d enter", __func__,__LINE__);
406 
407   // open FW binary file
408   if ((fptr = fopen(pfwImageCtx->default_fw_path, "rb")) == NULL) {
409     NXPLOG_FWDNLD_E("%s: Error! opening FW file %s\n", __func__,
410                     pfwImageCtx->default_fw_path);
411     status = FW_DNLD_FILE_NOT_FOUND;
412     goto exit;
413   }
414 
415   // find the FW binary file size
416   fseek(fptr, 0L, SEEK_END);
417   file_size = ftell(fptr);
418   if (!file_size || (-1L == file_size)) {
419     NXPLOG_FWDNLD_E("%s: Error! File %s is empty\n", __func__, pfwImageCtx->default_fw_path);
420     status = FW_DNLD_FAILURE;
421     goto exit;
422   }
423   else {
424     pfwImageCtx->fwImgSize = file_size;
425   }
426 
427   // read the FW bytes into buffer
428   pfwImageCtx->fwImage = (uint8_t *)malloc(sizeof(uint8_t) * pfwImageCtx->fwImgSize);
429   if (NULL == pfwImageCtx->fwImage)
430   {
431     status = FW_DNLD_FAILURE;
432     NXPLOG_FWDNLD_E("%s: Error in allocating memory\n", __func__);
433     goto exit;
434   }
435   rewind(fptr);
436   ret_size = fread(pfwImageCtx->fwImage, sizeof(uint8_t), pfwImageCtx->fwImgSize, fptr);
437   if (ret_size != pfwImageCtx->fwImgSize) {
438     if (feof(fptr))
439     {
440       NXPLOG_FWDNLD_E("%s: Error reading file %s, unexpected end of file\n",
441                       __func__, pfwImageCtx->default_fw_path);
442     }
443     else if (ferror(fptr))
444     {
445       NXPLOG_FWDNLD_E("%s: Error reading file %s\n", __func__, pfwImageCtx->default_fw_path);
446     }
447     status = FW_DNLD_FAILURE;
448     goto exit;
449   }
450 
451 exit:
452   if (NULL != fptr)
453   {
454     fclose(fptr);
455   }
456 
457   return status;
458 }
459 
460 /*******************************************************************************
461 **
462 ** Function    :   check_fw_update_required
463 **
464 ** Description :   This function checks whether FW update is required or not
465                    based on FW version from MW binary and FW version present in
466                    the HeliosX chip.
467 **
468 ** Parameters  :   getInfoRsp  - Struct which has the GetInfo response details.
469 **
470 ** Returns     :   FW_DNLD_FAILURE - If any un expected failure
471                    FW_DNLD_NOT_REQUIRED - FW update not required
472                    FW_DNLD_REQUIRED - FW update required
473                    FW_DNLD_FILE_NOT_FOUND - if the FW bin file is unable to
474                                                 open or not present
475 **
476 **
477 *******************************************************************************/
check_fw_update_required(phHDLLGetInfo_t * getInfoRsp)478 phFWD_Status_t check_fw_update_required(phHDLLGetInfo_t *getInfoRsp) {
479   uint32_t next_frame_first_byte_index = 0;
480   uint32_t index = 0;
481   uint8_t mw_fw_major_ver = 0;
482   uint8_t mw_fw_minor_ver = 0;
483   uint32_t frame_payload_length = 0;
484   uint32_t frame_length = 0;
485   unsigned long num = 0;
486   phFWD_Status_t status = FW_DNLD_FAILURE;
487 
488   fwImageCtx.deviceInfo = getInfoRsp;
489   fwImageCtx.fw_dnld_config = BIN_FILE_BASED_FW_DOWNLOAD;
490   fwImageCtx.fw_flash_config = FLASH_UPPER_VER_UPDATE;
491   fwImageCtx.fwRecovery = false;
492   strcpy(fwImageCtx.default_fw_path, default_fw_path);
493 
494   status = getFwImageCtx(&fwImageCtx);
495   if (status != FW_DNLD_SUCCESS) {
496     return status;
497   }
498 
499   if (NxpConfig_GetNum(NAME_NXP_UWB_FLASH_CONFIG, &num, sizeof(num))) {
500     fwImageCtx.fw_flash_config = (uint8_t)num;
501     NXPLOG_FWDNLD_D("NAME_NXP_UWB_FLASH_CONFIG: 0x%02x\n", fwImageCtx.fw_flash_config);
502     if (!(fwImageCtx.fw_flash_config == FLASH_UPPER_VER_UPDATE ||
503           fwImageCtx.fw_flash_config == FLASH_DIFFERENT_VER_UPDATE ||
504           fwImageCtx.fw_flash_config == FLASH_FORCE_UPDATE))
505     {
506       fwImageCtx.fw_flash_config = FLASH_UPPER_VER_UPDATE;
507     }
508   }
509   else {
510     NXPLOG_FWDNLD_D("NAME_NXP_UWB_FLASH_CONFIG: failed 0x%02x\n",
511                     fwImageCtx.fw_flash_config);
512   }
513 
514   frame_payload_length = (fwImageCtx.fwImage[next_frame_first_byte_index] << 8) +
515                          (fwImageCtx.fwImage[next_frame_first_byte_index + 1]);
516   frame_length = frame_payload_length + HDLL_HEADER_LEN + HDLL_FOOTER_LEN;
517 
518   // get the index of first_write_cmd_payload
519   next_frame_first_byte_index = next_frame_first_byte_index + frame_length;
520   index = next_frame_first_byte_index;
521   mw_fw_major_ver = fwImageCtx.fwImage[index + MW_MAJOR_FW_VER_OFFSET];
522   mw_fw_minor_ver = fwImageCtx.fwImage[index + MW_MINOR_FW_VER_OFFSET];
523   NXPLOG_FWDNLD_D("mw_fw_ver: %02X.%02X chip_fw_ver: %02X.%02X\n",
524                   mw_fw_major_ver, mw_fw_minor_ver, getInfoRsp->fw_major_ver,
525                   getInfoRsp->fw_minor_ver);
526 
527   if(getInfoRsp->session_control == SESSION_CONTROL_OPEN){
528     NXPLOG_FWDNLD_D("FW Update required as session control is open \n");
529     status = FW_DNLD_REQUIRED;
530   } else {
531     switch (fwImageCtx.fw_flash_config) {
532     case FLASH_UPPER_VER_UPDATE: {
533       if (mw_fw_major_ver > getInfoRsp->fw_major_ver) {
534         NXPLOG_FWDNLD_D("FLASH_UPPER_VER_UPDATE:FW Update required\n");
535         status = FW_DNLD_REQUIRED;
536       } else if (mw_fw_major_ver == getInfoRsp->fw_major_ver) {
537         if (mw_fw_minor_ver > getInfoRsp->fw_minor_ver) {
538           NXPLOG_FWDNLD_D("FLASH_UPPER_VER_UPDATE:FW Update required\n");
539           status = FW_DNLD_REQUIRED;
540         } else {
541           NXPLOG_FWDNLD_E(
542               "FLASH_UPPER_VER_UPDATE:FW lower Minor version is not supported\n");
543           status = FW_DNLD_NOT_REQUIRED;
544         }
545       } else {
546         NXPLOG_FWDNLD_E(
547             "FLASH_UPPER_VER_UPDATE:FW lower Major version is not supported\n");
548         status = FW_DNLD_NOT_REQUIRED;
549       }
550     } break;
551     case FLASH_FORCE_UPDATE: {
552       if (mw_fw_major_ver < getInfoRsp->fw_major_ver) {
553         NXPLOG_FWDNLD_E(
554             "FLASH_FORCE_UPDATE:FW lower Major version is not supported\n");
555         status = FW_DNLD_NOT_REQUIRED;
556       } else {
557         NXPLOG_FWDNLD_D("FLASH_FORCE_UPDATE:FW Update required\n");
558         status = FW_DNLD_REQUIRED;
559       }
560     } break;
561     case FLASH_DIFFERENT_VER_UPDATE: {
562       if (mw_fw_major_ver > getInfoRsp->fw_major_ver) {
563         NXPLOG_FWDNLD_D("FLASH_DIFFERENT_VER_UPDATE:FW Update required\n");
564         status = FW_DNLD_REQUIRED;
565       } else if(mw_fw_major_ver == getInfoRsp->fw_major_ver) {
566         if(mw_fw_minor_ver == getInfoRsp->fw_minor_ver) {
567           NXPLOG_FWDNLD_E(
568             "FLASH_DIFFERENT_VER_UPDATE:Same Minor FW version update is not supported\n");
569             status = FW_DNLD_NOT_REQUIRED;
570         } else {
571           NXPLOG_FWDNLD_E(
572             "FLASH_DIFFERENT_VER_UPDATE:FW Update required\n");
573             status = FW_DNLD_REQUIRED;
574         }
575       } else {
576         NXPLOG_FWDNLD_D("FLASH_DIFFERENT_VER_UPDATE:lower Major FW version update is not supported\n");
577         status = FW_DNLD_NOT_REQUIRED;;
578       }
579     } break;
580     }
581   }
582   return status;
583 }
584 
585 /*******************************************************************************
586 **
587 ** Function    :   handleGetInfoRsp
588 **
589 ** Description :   This function handles the GetInfo response that is received
590                    from the HeliosX chip.
591 **
592 ** Parameters  :   hdll_payload  - HDLL response buffer
593 **
594 ** Returns     :   FW_DNLD_FAILURE - If any un expected failure
595                    FW_DNLD_NOT_REQUIRED - FW update not required
596                    FW_DNLD_REQUIRED - FW update required
597                    FW_DNLD_FILE_NOT_FOUND - if the FW bin file is unable to
598                                                 open or not present
599 **
600 **
601 *******************************************************************************/
handleGetInfoRsp(uint8_t * hdll_payload)602 phFWD_Status_t handleGetInfoRsp(uint8_t *hdll_payload) {
603   phFWD_Status_t ret = FW_DNLD_FAILURE;
604   phHDLLGetInfo_t *getInfoRsp = NULL;
605 
606   getInfoRsp = process_getInfo_rsp(hdll_payload);
607   if (NULL == getInfoRsp) {
608     return ret;
609   }
610   print_getInfoRsp(getInfoRsp);
611   ret = check_fw_update_required(getInfoRsp);
612 
613   if (NULL != getInfoRsp) {
614     free(getInfoRsp);
615   }
616   return ret;
617 }
618 
619 /*******************************************************************************
620 **
621 ** Function    :   printHDLLRspStatus
622 **
623 ** Description :   This function prints the HDLL response status string based on
624                    the given status code
625 
626 ** Parameters  :   status  - status code
627 **
628 ** Returns     :   None
629 **
630 **
631 *******************************************************************************/
632 
printHDLLRspStatus(uint8_t status)633 void printHDLLRspStatus(uint8_t status) {
634   switch (status) {
635   case GENERIC_SUCCESS:
636     NXPLOG_FWDNLD_D("Received status: GENERIC_SUCCESS");
637     break;
638   case ACKNOWLEDGE:
639     NXPLOG_FWDNLD_D("Received status: ACKNOWLEDGE");
640     break;
641   case READY:
642     NXPLOG_FWDNLD_D("Received status: READY");
643     break;
644   case GENERIC_ERROR:
645     NXPLOG_FWDNLD_D("Received status: GENERIC_ERROR");
646     break;
647   case MEMORY_ERROR:
648     NXPLOG_FWDNLD_D("Received status: MEMORY_ERROR");
649     break;
650   case TIMEOUT_ERROR:
651     NXPLOG_FWDNLD_D("Received status: TIMEOUT_ERROR");
652     break;
653   case CRC_ERROR:
654     NXPLOG_FWDNLD_D("Received status: CRC_ERROR");
655     break;
656   case INVALID_ERROR:
657     NXPLOG_FWDNLD_D("Received status: INVALID_ERROR");
658     break;
659   case INVALID_LENGTH_ERROR:
660     NXPLOG_FWDNLD_D("Received status: INVALID_LENGTH_ERROR");
661     break;
662   case INVALID_ADDRESS_ERROR:
663     NXPLOG_FWDNLD_D("Received status: INVALID_ADDRESS_ERROR");
664     break;
665   case ECC_SIGNATURE_ERROR:
666     NXPLOG_FWDNLD_D("Received status: ECC_SIGNATURE_ERROR");
667     break;
668   case SHA384_HASH_ERROR:
669     NXPLOG_FWDNLD_D("Received status: SHA384_HASH_ERROR");
670     break;
671   case LIFECYCLE_VALIDITY_ERROR:
672     NXPLOG_FWDNLD_D("Received status: LIFECYCLE_VALIDITY_ERROR");
673     break;
674   case CHIP_ID_ERROR:
675     NXPLOG_FWDNLD_D("Received status: CHIP_ID_ERROR");
676     break;
677   case CHIP_VERSION_ERROR:
678     NXPLOG_FWDNLD_D("Received status: CHIP_VERSION_ERROR");
679     break;
680   case CERTIFICATE_VERSION_ERROR:
681     NXPLOG_FWDNLD_D("Received status: CERTIFICATE_VERSION_ERROR");
682     break;
683   case FIRMWARE_VERSION_ERROR:
684     NXPLOG_FWDNLD_D("Received status: FIRMWARE_VERSION_ERROR");
685     break;
686   case SRAM_DOWNLOAD_ALLOW_ERROR:
687     NXPLOG_FWDNLD_D("Received status: SRAM_DOWNLOAD_ALLOW_ERROR");
688     break;
689   case KEY_DERIVATION_ERROR:
690     NXPLOG_FWDNLD_D("Received status: KEY_DERIVATION_ERROR");
691     break;
692   case ENCRYPTED_PAYLOAD_DECRYPTION_ERROR:
693     NXPLOG_FWDNLD_D("Received status: ENCRYPTED_PAYLOAD_DECRYPTION_ERROR");
694     break;
695   case INVALID_ENCRYPTED_PAYLOAD_ERROR:
696     NXPLOG_FWDNLD_D("Received status: INVALID_ENCRYPTED_PAYLOAD_ERROR");
697     break;
698   case PROTECTED_CACHE_LOAD_ERROR:
699     NXPLOG_FWDNLD_D("Received status: PROTECTED_CACHE_LOAD_ERROR");
700     break;
701   case PROTECTED_CACHE_DEPLOY_ERROR:
702     NXPLOG_FWDNLD_D("Received status: PROTECTED_CACHE_DEPLOY_ERROR");
703     break;
704   case LIFECYCLE_UPDATE_ERROR:
705     NXPLOG_FWDNLD_D("Received status: LIFECYCLE_UPDATE_ERROR");
706     break;
707   case FLASH_BLANK_PAGE_ERROR:
708     NXPLOG_FWDNLD_D("Received status: FLASH_BLANK_PAGE_ERROR");
709     break;
710   case FLASH_CHECK_MARGIN_ERROR:
711     NXPLOG_FWDNLD_D("Received status: FLASH_CHECK_MARGIN_ERROR");
712     break;
713   default:
714     break;
715   };
716 }
717 
718 /*******************************************************************************
719 **
720 ** Function    :   process_hdll_response
721 **
722 ** Description :   This function processes the HDLL response
723 
724 ** Parameters  :   hdllCmdRsp  - HDLL command response structure which has the
725                                  received response info as well as the expected
726                                  response info.
727 **
728 ** Returns     :   FW_DNLD_FAILURE - If any undesired response received
729                    FW_DNLD_SUCCESS - On proper response
730 **
731 **
732 *******************************************************************************/
733 
734 /*
735  * HDLL Response:
736  * <-------HDLL Header--->|<------------------HDLL payload--------------------->
737  * <-------HDLL (2bytes)->|<-----HCP (2bytes)------->|<-Application--> <--CRC-->
738  * <31 30> <29>  <28 -16> |<15 -14><13 - 8> <7 - 0>  |<status><Payload><2 bytes>
739  * <--R--><Chunk><length> |< Type ><Group><Operation>|<1 byte>
740  *
741  */
process_hdll_response(phHDLLCmdRsp_t * hdllCmdRsp)742 phFWD_Status_t process_hdll_response(phHDLLCmdRsp_t *hdllCmdRsp) {
743   uint8_t hdll_msg_type = 0;
744   uint8_t hdll_rsp_status = 0;
745   uint16_t hdll_packet_len = 0;
746   uint8_t hdll_group = 0;
747   uint8_t hdll_operation = 0;
748   uint8_t *hdll_payload = NULL;
749   uint16_t hdll_payload_len = 0;
750   phFWD_Status_t ret = FW_DNLD_FAILURE;
751 
752   if (hdllCmdRsp == NULL || hdllCmdRsp->rsp_buf == NULL) {
753     NXPLOG_FWDNLD_E("%s HDLL response buffer is NULL\n", __func__);
754     return ret;
755   }
756   if (hdllCmdRsp->rsp_buf_len < HDLL_MIN_RSP_LEN) {
757     NXPLOG_FWDNLD_E(
758         "%s Error! HDLL response buffer length is %d, expected min %d bytes\n",
759         __func__, hdllCmdRsp->rsp_buf_len, HDLL_MIN_RSP_LEN);
760     return ret;
761   }
762 
763   // parse hdll frame
764   hdll_packet_len = (uint16_t)(hdllCmdRsp->rsp_buf[0] << 8) |
765                     (hdllCmdRsp->rsp_buf[HDLL_LEN_OFFSET]);
766   hdll_packet_len &= HDLL_PKT_LEN_BITMASK;
767   NXPLOG_FWDNLD_D("Received RSP packet len      :0x%04X\n", hdll_packet_len);
768   if (hdll_packet_len == 0) {
769     NXPLOG_FWDNLD_D("Error in hdll response.. hdll_packet_len = 0\n");
770     return ret;
771   }
772 
773   hdll_msg_type = hdllCmdRsp->rsp_buf[HDLL_TYPE_OFFSET] >> HCP_GROUP_LEN;
774   hdll_group =
775       (hdllCmdRsp->rsp_buf[HDLL_GROUP_OFFSET] & HDLL_RSP_GROUP_BIT_MASK);
776   hdll_operation = hdllCmdRsp->rsp_buf[HDLL_OPERATION_OFFSET];
777   hdll_rsp_status = hdllCmdRsp->rsp_buf[HDLL_RSP_STATUS_OFFSET];
778 
779   NXPLOG_FWDNLD_D("Received RSP msg type        :0x%02X\n", hdll_msg_type);
780   NXPLOG_FWDNLD_D("Received RSP group operation :0x%02X%02X\n", hdll_group,
781                   hdll_operation);
782   NXPLOG_FWDNLD_D("Received RSP status code     :0x%02X\n", hdll_rsp_status);
783   printHDLLRspStatus(hdll_rsp_status);
784 
785   hdll_payload_len = hdllCmdRsp->rsp_buf_len - (HDLL_RSP_PAYLOAD_OFFSET + HDLL_CRC_LEN);
786   NXPLOG_FWDNLD_D("hdll payload len = 0x%02x" , hdll_payload_len);
787 
788   if (hdll_payload_len > 0) {
789     hdll_payload = (uint8_t *)malloc(
790         sizeof(uint8_t) *
791         (hdll_payload_len));
792     if (NULL == hdll_payload) {
793       return ret;
794     }
795     memcpy(hdll_payload, &hdllCmdRsp->rsp_buf[HDLL_RSP_PAYLOAD_OFFSET],
796            hdll_payload_len);
797   }
798 
799   // validate the response
800   if (hdllCmdRsp->status != hdll_rsp_status) {
801     NXPLOG_FWDNLD_D("Error! expected response status code is 0x%02X  but "
802                     "received 0x%02X\n",
803                     hdllCmdRsp->status, hdll_rsp_status);
804     ret = FW_DNLD_FAILURE;
805   } else if (hdllCmdRsp->type != hdll_msg_type) {
806     NXPLOG_FWDNLD_D(
807         "Error! expected HDLL type code is 0x%02X but received 0x%02X\n",
808         hdllCmdRsp->type, hdll_msg_type);
809     ret = FW_DNLD_FAILURE;
810   } else if ((hdllCmdRsp->group != hdll_group) ||
811            (hdllCmdRsp->operation != hdll_operation)) {
812     NXPLOG_FWDNLD_D("Error! expected response operation code is 0x%02X%02X but "
813                     "received 0x%02X%02X \n",
814                     hdllCmdRsp->group, hdllCmdRsp->operation, hdll_group,
815                     hdll_operation);
816     ret = FW_DNLD_FAILURE;
817   } else
818   {
819     ret = FW_DNLD_SUCCESS;
820   }
821 
822   if (ret == FW_DNLD_FAILURE){
823     goto exit;
824   }
825 
826   // Handle the response according to the operation
827   switch (hdll_group) {
828   case HCP_OPERATION_GROUP_PROTOCOL: {
829     switch (hdll_operation) {
830     case PROTOCOL_GROUP_OP_CODE_HDLL: {
831       NXPLOG_FWDNLD_D("Received PROTOCOL_GROUP_HDLL_OP_CODE\n");
832     } break;
833     case PROTOCOL_GROUP_OP_CODE_HCP: {
834       NXPLOG_FWDNLD_D("Received PROTOCOL_GROUP_HCP_OP_CODE\n");
835     } break;
836     case PROTOCOL_GROUP_OP_CODE_EDL: {
837       NXPLOG_FWDNLD_D("Received PROTOCOL_GROUP_EDL_OP_CODE\n");
838     } break;
839     }
840   } break;
841 
842   case HCP_OPERATION_GROUP_GENERIC: {
843     switch (hdll_operation) {
844     case GENERIC_GROUP_OP_CODE_RESET: {
845       NXPLOG_FWDNLD_D("Received OP_GENERIC_RESET\n");
846       // Generic reset cmd will have the rsp only in case of error.
847       // How to handle the situation.
848     } break;
849     case GENERIC_GROUP_OP_CODE_GETINFO: {
850       NXPLOG_FWDNLD_D("Received OP_GENERIC_GET_INFO\n");
851       if (hdll_payload != NULL) {
852         ret = handleGetInfoRsp(hdll_payload);
853       }
854     } break;
855     }
856   } break;
857 
858   case HCP_OPERATION_GROUP_EDL: {
859     switch (hdll_operation) {
860     case EDL_DOWNLOAD_CERTIFICATE: {
861       NXPLOG_FWDNLD_D("Received OP_EDL_DOWNLOAD_CERTIFICATE\n");
862     } break;
863     case EDL_DOWNLOAD_FLASH_WRITE_FIRST: {
864       NXPLOG_FWDNLD_D("Received OP_EDL_DOWNLOAD_FLASH_WRITE_FIRST\n");
865     }
866     break;
867     case EDL_DOWNLOAD_FLASH_WRITE: {
868       NXPLOG_FWDNLD_D("Received OP_EDL_DOWNLOAD_FLASH_WRITE\n");
869     } break;
870     case EDL_DOWNLOAD_FLASH_WRITE_LAST: {
871       NXPLOG_FWDNLD_D("Received OP_EDL_DOWNLOAD_FLASH_WRITE_LAST\n");
872     } break;
873     case EDL_DOWNLOAD_SRAM_WRITE_FIRST: {
874       NXPLOG_FWDNLD_D("Received OP_EDL_DOWNLOAD_SRAM_WRITE_FIRST\n");
875     } break;
876     case EDL_DOWNLOAD_SRAM_WRITE: {
877       NXPLOG_FWDNLD_D("Received OP_EDL_DOWNLOAD_SRAM_WRITE\n");
878     } break;
879     case EDL_DOWNLOAD_SRAM_WRITE_LAST: {
880       NXPLOG_FWDNLD_D("Received OP_EDL_DOWNLOAD_SRAM_WRITE_LAST\n");
881     } break;
882     case EDL_LIFECYCLE_CERTIFICATE: {
883       NXPLOG_FWDNLD_D("Received OP_EDL_LIFECYCLE_CERTIFICATE\n");
884     } break;
885     case EDL_LIFECYCLE_WRITE_FIRST: {
886       NXPLOG_FWDNLD_D("Received OP_EDL_LIFECYCLE_WRITE_FIRST\n");
887     } break;
888     case EDL_LIFECYCLE_WRITE_LAST: {
889       NXPLOG_FWDNLD_D("Received OP_EDL_LIFECYCLE_WRITE_LAST\n");
890     } break;
891     case EDL_PATCH_SRAM_WRITE: {
892       NXPLOG_FWDNLD_D("Received OP_EDL_PATCH_SRAM_WRITE\n");
893     } break;
894     case EDL_PATCH_SRAM_WRITE_LAST: {
895       NXPLOG_FWDNLD_D("Received OP_EDL_PATCH_SRAM_WRITE_LAST\n");
896     } break;
897     case EDL_PATCH_FLASH_WRITE: {
898       NXPLOG_FWDNLD_D("Received OP_EDL_PATCH_FLASH_WRITE\n");
899     } break;
900     }
901   } break;
902   default:
903     break;
904   }
905 
906 exit:
907   if (hdll_payload != NULL) {
908     free(hdll_payload);
909   }
910   return ret;
911 }
912 
913 /*******************************************************************************
914 **
915 ** Function    :   sendEdlDownloadCertificateCmd
916 **
917 ** Description :   This function frames the EdlDownloadCertificateCmd which
918                    needs to be sent as part of FW download sequence.
919 **
920 ** Parameters  :   payload  - HDLL command buffer
921                    len - command buffer length
922                    rsp_buf - response buffer that will be received from the
923                    HeliosX chip.
924 **
925 ** Returns     :   FW_DNLD_FAILURE - If any undesired response received
926                    FW_DNLD_SUCCESS - On proper response
927 **
928 **
929 *******************************************************************************/
sendEdlDownloadCertificateCmd(uint8_t * payload,uint16_t len,uint8_t * rsp_buf)930 phFWD_Status_t sendEdlDownloadCertificateCmd(uint8_t *payload, uint16_t len,
931                                              uint8_t *rsp_buf) {
932 
933   uint16_t rsp_buf_len = 0x0;
934   phFWD_Status_t ret = FW_DNLD_SUCCESS;
935   phHDLLCmdRsp_t *hdllCmdRsp = NULL;
936 
937   ret = phGenericSendAndRecv(payload, len, rsp_buf, &rsp_buf_len);
938   if (!rsp_buf_len || ret == FW_DNLD_FAILURE) {
939     NXPLOG_FWDNLD_D("Error in sending/receiving OP_EDL_DOWNLOAD_CERTIFICATE "
940                     "cmd/response\n");
941     return ret;
942   }
943 
944   hdllCmdRsp = (phHDLLCmdRsp_t *)malloc(sizeof(phHDLLCmdRsp_t));
945   if (NULL == hdllCmdRsp) {
946     return ret;
947   }
948 
949   hdllCmdRsp->group = HCP_OPERATION_GROUP_EDL;
950   hdllCmdRsp->operation = EDL_DOWNLOAD_CERTIFICATE;
951   hdllCmdRsp->rsp_buf = rsp_buf;
952   hdllCmdRsp->rsp_buf_len = rsp_buf_len;
953   hdllCmdRsp->status = GENERIC_SUCCESS;
954   hdllCmdRsp->type = HCP_TYPE_RESPONSE;
955   ret = process_hdll_response(hdllCmdRsp);
956 
957   if (NULL != hdllCmdRsp) {
958     free(hdllCmdRsp);
959   }
960 
961   return ret;
962 }
963 
964 /*******************************************************************************
965 **
966 ** Function    :   sendEdlFlashWriteFirstCmd
967 **
968 ** Description :   This function frames the EdlFlashWriteFirstCmd which
969                    needs to be sent as part of FW download sequence.
970 **
971 ** Parameters  :   payload  - HDLL command buffer
972                    len - command buffer length
973                    rsp_buf - response buffer that will be received from the
974                    HeliosX chip.
975 **
976 ** Returns     :   FW_DNLD_FAILURE - If any undesired response received
977                    FW_DNLD_SUCCESS - On proper response
978 **
979 **
980 *******************************************************************************/
sendEdlFlashWriteFirstCmd(uint8_t * payload,uint16_t len,uint8_t * rsp_buf)981 phFWD_Status_t sendEdlFlashWriteFirstCmd(uint8_t *payload, uint16_t len,
982                                          uint8_t *rsp_buf) {
983   uint16_t rsp_buf_len = 0x0;
984   phFWD_Status_t ret = FW_DNLD_SUCCESS;
985   phHDLLCmdRsp_t *hdllCmdRsp = NULL;
986 
987   ret = phGenericSendAndRecv(payload, len, rsp_buf, &rsp_buf_len);
988   if (!rsp_buf_len || ret == FW_DNLD_FAILURE) {
989     NXPLOG_FWDNLD_D("Error in sending/receiving "
990                     "OP_EDL_DOWNLOAD_FLASH_WRITE_FIRST cmd/response\n");
991     return ret;
992   }
993 
994   hdllCmdRsp = (phHDLLCmdRsp_t *)malloc(sizeof(phHDLLCmdRsp_t));
995   if (NULL == hdllCmdRsp) {
996     return ret;
997   }
998 
999   hdllCmdRsp->group = HCP_OPERATION_GROUP_EDL;
1000   hdllCmdRsp->operation = EDL_DOWNLOAD_FLASH_WRITE_FIRST;
1001   hdllCmdRsp->rsp_buf = rsp_buf;
1002   hdllCmdRsp->rsp_buf_len = rsp_buf_len;
1003   hdllCmdRsp->status = GENERIC_SUCCESS;
1004   hdllCmdRsp->type = HCP_TYPE_RESPONSE;
1005   ret = process_hdll_response(hdllCmdRsp);
1006 
1007   if (NULL != hdllCmdRsp) {
1008     free(hdllCmdRsp);
1009   }
1010 
1011   return ret;
1012 }
1013 
1014 /*******************************************************************************
1015 **
1016 ** Function    :   sendEdlFlashWriteCmd
1017 **
1018 ** Description :   This function frames the sendEdlFlashWriteCmd which
1019                    will have the actual FW chunk.
1020 **
1021 ** Parameters  :   payload  - HDLL command buffer
1022                    len - command buffer length
1023                    rsp_buf - response buffer that will be received from the
1024                    HeliosX chip.
1025 **
1026 ** Returns     :   FW_DNLD_FAILURE - If any undesired response received
1027                    FW_DNLD_SUCCESS - On proper response
1028 **
1029 **
1030 *******************************************************************************/
sendEdlFlashWriteCmd(uint8_t * payload,uint16_t len,uint8_t * rsp_buf)1031 phFWD_Status_t sendEdlFlashWriteCmd(uint8_t *payload, uint16_t len,
1032                                     uint8_t *rsp_buf) {
1033   uint16_t rsp_buf_len = 0x0;
1034   phFWD_Status_t ret = FW_DNLD_SUCCESS;
1035   phHDLLCmdRsp_t *hdllCmdRsp = NULL;
1036 
1037   ret = phGenericSendAndRecv(payload, len, rsp_buf, &rsp_buf_len);
1038   if (!rsp_buf_len || ret == FW_DNLD_FAILURE) {
1039     NXPLOG_FWDNLD_D("Error in sending/receiving OP_EDL_DOWNLOAD_FLASH_WRITE "
1040                     "cmd/response\n");
1041     return ret;
1042   }
1043 
1044   hdllCmdRsp = (phHDLLCmdRsp_t *)malloc(sizeof(phHDLLCmdRsp_t));
1045   if (NULL == hdllCmdRsp) {
1046     return ret;
1047   }
1048 
1049   hdllCmdRsp->group = HCP_OPERATION_GROUP_EDL;
1050   hdllCmdRsp->operation = EDL_DOWNLOAD_FLASH_WRITE;
1051   hdllCmdRsp->rsp_buf = rsp_buf;
1052   hdllCmdRsp->rsp_buf_len = rsp_buf_len;
1053   hdllCmdRsp->status = GENERIC_SUCCESS;
1054   hdllCmdRsp->type = HCP_TYPE_RESPONSE;
1055   ret = process_hdll_response(hdllCmdRsp);
1056 
1057   if (NULL != hdllCmdRsp) {
1058     free(hdllCmdRsp);
1059   }
1060 
1061   return ret;
1062 }
1063 
1064 /*******************************************************************************
1065 **
1066 ** Function    :   sendEdlFlashWriteLastCmd
1067 **
1068 ** Description :   This function frames the EdlFlashWriteLastCmd which
1069                    needs to be sent as part of FW download sequence.
1070 **
1071 ** Parameters  :   payload  - HDLL command buffer
1072                    len - command buffer length
1073                    rsp_buf - response buffer that will be received from the
1074                    HeliosX chip.
1075 **
1076 ** Returns     :   FW_DNLD_FAILURE - If any undesired response received
1077                    FW_DNLD_SUCCESS - On proper response
1078 **
1079 **
1080 *******************************************************************************/
sendEdlFlashWriteLastCmd(uint8_t * payload,uint16_t len,uint8_t * rsp_buf)1081 phFWD_Status_t sendEdlFlashWriteLastCmd(uint8_t *payload, uint16_t len,
1082                                         uint8_t *rsp_buf) {
1083   uint16_t rsp_buf_len = 0x0;
1084   phFWD_Status_t ret = FW_DNLD_SUCCESS;
1085   phHDLLCmdRsp_t *hdllCmdRsp = NULL;
1086 
1087   ret = phGenericSendAndRecv(payload, len, rsp_buf, &rsp_buf_len);
1088   if (!rsp_buf_len || ret == FW_DNLD_FAILURE) {
1089     NXPLOG_FWDNLD_D("Error in sending/receiving "
1090                     "OP_EDL_DOWNLOAD_FLASH_WRITE_LAST cmd/response\n");
1091     return ret;
1092   }
1093 
1094   hdllCmdRsp = (phHDLLCmdRsp_t *)malloc(sizeof(phHDLLCmdRsp_t));
1095   if (NULL == hdllCmdRsp) {
1096     return ret;
1097   }
1098 
1099   hdllCmdRsp->group = HCP_OPERATION_GROUP_EDL;
1100   hdllCmdRsp->operation = EDL_DOWNLOAD_FLASH_WRITE_LAST;
1101   hdllCmdRsp->rsp_buf = rsp_buf;
1102   hdllCmdRsp->rsp_buf_len = rsp_buf_len;
1103   hdllCmdRsp->status = GENERIC_SUCCESS;
1104   hdllCmdRsp->type = HCP_TYPE_RESPONSE;
1105   ret = process_hdll_response(hdllCmdRsp);
1106 
1107   if (NULL != hdllCmdRsp) {
1108     free(hdllCmdRsp);
1109   }
1110 
1111   return ret;
1112 }
1113 
1114 /*******************************************************************************
1115 **
1116 ** Function    :   sendEdlLifecycleCertificateCmd
1117 **
1118 ** Description :   This function frames the EdlLifecycleCertificateCmd which
1119                    needs to be sent as part of Lifecycle update.
1120 **
1121 ** Parameters  :   payload  - HDLL command buffer
1122                    len - command buffer length
1123                    rsp_buf - response buffer that will be received from the
1124                    HeliosX chip.
1125 **
1126 ** Returns     :   FW_DNLD_FAILURE - If any undesired response received
1127                    FW_DNLD_SUCCESS - On proper response
1128 **
1129 **
1130 *******************************************************************************/
sendEdlLifecycleCertificateCmd(uint8_t * payload,uint16_t len,uint8_t * rsp_buf)1131 phFWD_Status_t sendEdlLifecycleCertificateCmd(uint8_t *payload, uint16_t len,
1132                                               uint8_t *rsp_buf) {
1133   uint16_t rsp_buf_len = 0x0;
1134   phFWD_Status_t ret = FW_DNLD_SUCCESS;
1135   phHDLLCmdRsp_t *hdllCmdRsp = NULL;
1136 
1137   ret = phGenericSendAndRecv(payload, len, rsp_buf, &rsp_buf_len);
1138   if (!rsp_buf_len || ret == FW_DNLD_FAILURE) {
1139     NXPLOG_FWDNLD_D("Error in sending/receiving "
1140                     "EDL_LIFECYCLE_CERTIFICATE cmd/response\n");
1141     return ret;
1142   }
1143 
1144   hdllCmdRsp = (phHDLLCmdRsp_t *)malloc(sizeof(phHDLLCmdRsp_t));
1145   if (NULL == hdllCmdRsp) {
1146     return ret;
1147   }
1148 
1149   hdllCmdRsp->group = HCP_OPERATION_GROUP_EDL;
1150   hdllCmdRsp->operation = EDL_LIFECYCLE_CERTIFICATE;
1151   hdllCmdRsp->rsp_buf = rsp_buf;
1152   hdllCmdRsp->rsp_buf_len = rsp_buf_len;
1153   hdllCmdRsp->status = GENERIC_SUCCESS;
1154   hdllCmdRsp->type = HCP_TYPE_RESPONSE;
1155   ret = process_hdll_response(hdllCmdRsp);
1156 
1157   if (NULL != hdllCmdRsp) {
1158     free(hdllCmdRsp);
1159   }
1160 
1161   return ret;
1162 }
1163 
1164 /*******************************************************************************
1165 **
1166 ** Function    :   sendEdlLifecycleWriteFirstCmd
1167 **
1168 ** Description :   This function frames the EdlLifecycleWriteFirstCmd which
1169                    needs to be sent as part of Lifecycle update.
1170 **
1171 ** Parameters  :   payload  - HDLL command buffer
1172                    len - command buffer length
1173                    rsp_buf - response buffer that will be received from the
1174                    HeliosX chip.
1175 **
1176 ** Returns     :   FW_DNLD_FAILURE - If any undesired response received
1177                    FW_DNLD_SUCCESS - On proper response
1178 **
1179 **
1180 *******************************************************************************/
sendEdlLifecycleWriteFirstCmd(uint8_t * payload,uint16_t len,uint8_t * rsp_buf)1181 phFWD_Status_t sendEdlLifecycleWriteFirstCmd(uint8_t *payload, uint16_t len,
1182                                              uint8_t *rsp_buf) {
1183   uint16_t rsp_buf_len = 0x0;
1184   phFWD_Status_t ret = FW_DNLD_SUCCESS;
1185   phHDLLCmdRsp_t *hdllCmdRsp = NULL;
1186 
1187   ret = phGenericSendAndRecv(payload, len, rsp_buf, &rsp_buf_len);
1188   if (!rsp_buf_len || ret == FW_DNLD_FAILURE) {
1189     NXPLOG_FWDNLD_D("Error in sending/receiving "
1190                     "EDL_LIFECYCLE_WRITE_FIRST cmd/response\n");
1191     return ret;
1192   }
1193 
1194   hdllCmdRsp = (phHDLLCmdRsp_t *)malloc(sizeof(phHDLLCmdRsp_t));
1195   if (NULL == hdllCmdRsp) {
1196     return ret;
1197   }
1198 
1199   hdllCmdRsp->group = HCP_OPERATION_GROUP_EDL;
1200   hdllCmdRsp->operation = EDL_LIFECYCLE_WRITE_FIRST;
1201   hdllCmdRsp->rsp_buf = rsp_buf;
1202   hdllCmdRsp->rsp_buf_len = rsp_buf_len;
1203   hdllCmdRsp->status = GENERIC_SUCCESS;
1204   hdllCmdRsp->type = HCP_TYPE_RESPONSE;
1205   ret = process_hdll_response(hdllCmdRsp);
1206 
1207   if (NULL != hdllCmdRsp) {
1208     free(hdllCmdRsp);
1209   }
1210 
1211   return ret;
1212 }
1213 
1214 /*******************************************************************************
1215 **
1216 ** Function    :   sendEdlLifecycleWriteLastCmd
1217 **
1218 ** Description :   This function frames the EdlLifecycleWriteLastCmd which
1219                    needs to be sent as part of Lifecycle update.
1220 **
1221 ** Parameters  :   payload  - HDLL command buffer
1222                    len - command buffer length
1223                    rsp_buf - response buffer that will be received from the
1224                    HeliosX chip.
1225 **
1226 ** Returns     :   FW_DNLD_FAILURE - If any undesired response received
1227                    FW_DNLD_SUCCESS - On proper response
1228 **
1229 **
1230 *******************************************************************************/
sendEdlLifecycleWriteLastCmd(uint8_t * payload,uint16_t len,uint8_t * rsp_buf)1231 phFWD_Status_t sendEdlLifecycleWriteLastCmd(uint8_t *payload, uint16_t len,
1232                                             uint8_t *rsp_buf) {
1233   uint16_t rsp_buf_len = 0x0;
1234   phFWD_Status_t ret = FW_DNLD_SUCCESS;
1235   phHDLLCmdRsp_t *hdllCmdRsp = NULL;
1236 
1237   ret = phGenericSendAndRecv(payload, len, rsp_buf, &rsp_buf_len);
1238   if (!rsp_buf_len || ret == FW_DNLD_FAILURE) {
1239     NXPLOG_FWDNLD_D("Error in sending/receiving "
1240                     "EDL_LIFECYCLE_WRITE_LAST cmd/response\n");
1241     return ret;
1242   }
1243 
1244   hdllCmdRsp = (phHDLLCmdRsp_t *)malloc(sizeof(phHDLLCmdRsp_t));
1245   if (NULL == hdllCmdRsp) {
1246     return ret;
1247   }
1248 
1249   hdllCmdRsp->group = HCP_OPERATION_GROUP_EDL;
1250   hdllCmdRsp->operation = EDL_LIFECYCLE_WRITE_LAST;
1251   hdllCmdRsp->rsp_buf = rsp_buf;
1252   hdllCmdRsp->rsp_buf_len = rsp_buf_len;
1253   hdllCmdRsp->status = GENERIC_SUCCESS;
1254   hdllCmdRsp->type = HCP_TYPE_RESPONSE;
1255   ret = process_hdll_response(hdllCmdRsp);
1256 
1257   if (NULL != hdllCmdRsp) {
1258     free(hdllCmdRsp);
1259   }
1260 
1261   return ret;
1262 }
1263 
1264 /*******************************************************************************
1265 **
1266 ** Function    :   sendEdlPatchFlashWriteCmd
1267 **
1268 ** Description :   This function frames the sendEdlPatchlFlashWriteCmd which
1269                    will send the EDL Patch Flash Write cmd
1270 **
1271 ** Parameters  :   payload  - HDLL command buffer
1272                    len - command buffer length
1273                    rsp_buf - response buffer that will be received from the
1274                    HeliosX chip.
1275 **
1276 ** Returns     :   FW_DNLD_FAILURE - If any undesired response received
1277                    FW_DNLD_SUCCESS - On proper response
1278 **
1279 **
1280 *******************************************************************************/
sendEdlPatchFlashWriteCmd(uint8_t * payload,uint16_t len,uint8_t * rsp_buf)1281 phFWD_Status_t sendEdlPatchFlashWriteCmd(uint8_t *payload, uint16_t len,
1282                                     uint8_t *rsp_buf) {
1283   uint16_t rsp_buf_len = 0x0;
1284   phFWD_Status_t ret = FW_DNLD_SUCCESS;
1285   phHDLLCmdRsp_t *hdllCmdRsp = NULL;
1286 
1287   ret = phGenericSendAndRecv(payload, len, rsp_buf, &rsp_buf_len);
1288   if (!rsp_buf_len || ret == FW_DNLD_FAILURE) {
1289     NXPLOG_FWDNLD_D("Error in sending/receiving OP_EDL_PATCH_FLASH_WRITE "
1290                     "cmd/response\n");
1291     return ret;
1292   }
1293 
1294   hdllCmdRsp = (phHDLLCmdRsp_t *)malloc(sizeof(phHDLLCmdRsp_t));
1295   if (NULL == hdllCmdRsp) {
1296     return ret;
1297   }
1298 
1299   hdllCmdRsp->group = HCP_OPERATION_GROUP_EDL;
1300   hdllCmdRsp->operation = EDL_PATCH_FLASH_WRITE;
1301   hdllCmdRsp->rsp_buf = rsp_buf;
1302   hdllCmdRsp->rsp_buf_len = rsp_buf_len;
1303   hdllCmdRsp->status = GENERIC_SUCCESS;
1304   hdllCmdRsp->type = HCP_TYPE_RESPONSE;
1305   ret = process_hdll_response(hdllCmdRsp);
1306 
1307   if (NULL != hdllCmdRsp) {
1308     free(hdllCmdRsp);
1309   }
1310 
1311   return ret;
1312 }
1313 
1314 /*******************************************************************************
1315 **
1316 ** Function    :   phHal_Host_CalcCrc16
1317 **
1318 ** Description :   This function calculates the HDLL command's CRC
1319 **
1320 ** Parameters  :   p  - HDLL command buffer
1321                    dwLength - command buffer length
1322 **
1323 ** Returns     :   the calculated CRC value
1324 **
1325 **
1326 *******************************************************************************/
phHal_Host_CalcCrc16(uint8_t * p,uint32_t dwLength)1327 static uint16_t phHal_Host_CalcCrc16(uint8_t *p, uint32_t dwLength) {
1328   uint32_t i;
1329   uint16_t crc_new;
1330   uint16_t crc = 0xffffU;
1331 
1332   for (i = 0; i < dwLength; i++) {
1333     crc_new = (uint8_t)(crc >> 8) | (crc << 8);
1334     crc_new ^= p[i];
1335     crc_new ^= (uint8_t)(crc_new & 0xff) >> 4;
1336     crc_new ^= crc_new << 12;
1337     crc_new ^= (crc_new & 0xff) << 5;
1338     crc = crc_new;
1339   }
1340   return crc;
1341 }
1342 
1343 /*******************************************************************************
1344 **
1345 ** Function    :   phBuildHdllCmd
1346 **
1347 ** Description :   This function frames the final HDLL command (HDLL header +
1348                    HDLL payload + CRC) by framing HDLL payload and HDLL frame
1349                    using 2 different APIs.
1350 **
1351 ** Parameters  :   hdllCmd - HDLL command structure which has the information
1352                              to build the corresponding HDLL command.
1353 **
1354 ** Returns     :   NULL - on failure
1355                    HDLL command buffer - On success
1356 **
1357 **
1358 *******************************************************************************/
1359 
1360 /*
1361  * HDLL Command:
1362  * <--------HDLL Header---->|<------------------HDLL payload------------------->
1363  * <--------HDLL (2bytes)-->|<-----HCP (2bytes)------->|<-Application-><--CRC-->
1364  * <31 30> <29>    <28 -16> |<15 -14><13 - 8><7 - 0>   |<---Payload---><2 bytes>
1365  * <--R--> <Chunk> <length> |< Type ><Group><Operation>|
1366  *
1367  */
1368 
phBuildHdllCmd(phHDLLCmd_t * hdllCmd)1369 uint8_t *phBuildHdllCmd(phHDLLCmd_t *hdllCmd) {
1370   uint8_t type = 0;
1371   uint8_t *hdll_frame = NULL;
1372   uint16_t hdll_frame_size = 0;
1373   uint16_t hdll_crc = 0x0;
1374   uint16_t hdll_header = 0x0;
1375   NXPLOG_FWDNLD_D("phBuildHdllCmd:\n");
1376 
1377   if (NULL == hdllCmd) {
1378     return NULL;
1379   }
1380   // header len =2 bytes + hdll_payload_len + crc =2 bytes
1381   hdll_frame_size = HDLL_HEADER_LEN + HCP_MSG_HEADER_LEN +
1382                     hdllCmd->payload_len + HDLL_CRC_LEN;
1383   hdll_frame = (uint8_t *)malloc(sizeof(uint8_t) * hdll_frame_size);
1384   if (NULL == hdll_frame) {
1385     return hdll_frame;
1386   }
1387 
1388   // build hdll frame
1389   hdll_header |= hdllCmd->payload_len + HCP_MSG_HEADER_LEN;
1390   hdll_header &= HDLL_PKT_LEN_BITMASK;
1391   hdll_header = hdllCmd->chunk_size ? (HDLL_PKT_CHUNK_BITMASK | hdll_header)
1392                                     : hdll_header;
1393 
1394   // hdll_header uint16 to uint8
1395   hdll_frame[HDLL_CHUNK_OFFSET] = (hdll_header >> 8);
1396   hdll_frame[HDLL_LEN_OFFSET] = (hdll_header & 0xFF);
1397 
1398   type = HCP_TYPE_COMMAND;
1399   type <<= HCP_GROUP_LEN;
1400   hdll_frame[HDLL_TYPE_OFFSET] = type | hdllCmd->group;
1401   hdll_frame[HDLL_OPERATION_OFFSET] = hdllCmd->operation;
1402 
1403   if (hdllCmd->payload_len > 0 && hdllCmd->payload != NULL) {
1404     // copy hdll payload into hdll frame
1405     memcpy(&hdll_frame[HDLL_PAYLOAD_OFFSET], hdllCmd->payload,
1406            hdllCmd->payload_len);
1407   }
1408 
1409   hdll_crc = phHal_Host_CalcCrc16(hdll_frame, hdll_frame_size - 2);
1410   hdll_frame[hdll_frame_size - 2] = (hdll_crc >> 8);
1411   hdll_frame[hdll_frame_size - 1] = (hdll_crc & 0xFF);
1412 
1413   hdllCmd->frame_size = hdll_frame_size;
1414   return hdll_frame;
1415 }
1416 
1417 /*******************************************************************************
1418 **
1419 ** Function    :   sendEdlResetCmd
1420 **
1421 ** Description :   This function frames the EdlResetCmd and sends to the HeliosX
1422                    chip
1423 **
1424 ** Parameters  :   None
1425 **
1426 ** Returns     :   FW_DNLD_FAILURE - If any failure occurs while framing or
1427                                     sending the command or while receiving the
1428                                     response
1429                    FW_DNLD_SUCCESS - On success
1430 **
1431 **
1432 *******************************************************************************/
sendEdlResetCmd()1433 phFWD_Status_t sendEdlResetCmd() {
1434   uint8_t rsp_buf[HDLL_READ_BUFF_SIZE] = {0};
1435   uint8_t *hdll_frame = NULL;
1436   phFWD_Status_t ret = FW_DNLD_FAILURE;
1437   uint16_t rsp_buf_len = 0x0;
1438   phHDLLCmd_t *hdllCmd = NULL;
1439   phHDLLCmdRsp_t *hdllCmdRsp = NULL;
1440 
1441   hdllCmd = (phHDLLCmd_t *)malloc(sizeof(phHDLLCmd_t));
1442   if (NULL == hdllCmd) {
1443     goto exit;
1444   }
1445 
1446   hdllCmd->group = HCP_OPERATION_GROUP_GENERIC;
1447   hdllCmd->operation = GENERIC_GROUP_OP_CODE_RESET;
1448   hdllCmd->chunk_size = 0;
1449   hdllCmd->frame_size = 0;
1450   hdllCmd->payload = NULL;
1451   hdllCmd->payload_len = 0;
1452 
1453   hdll_frame = phBuildHdllCmd(hdllCmd);
1454   if (NULL == hdll_frame) {
1455     goto exit;
1456   }
1457   NXPLOG_FWDNLD_D("Sending operation: OP_GENERIC_RESET\n");
1458   ret = phGenericSendAndRecv(hdll_frame, hdllCmd->frame_size, rsp_buf,
1459                              &rsp_buf_len);
1460   if (ret == FW_DNLD_FAILURE) {
1461     // treat is as success as generic reset will have response only if there
1462     // is an error.
1463     ret = FW_DNLD_SUCCESS;
1464   }
1465   if (rsp_buf_len > 0) {
1466     hdllCmdRsp = (phHDLLCmdRsp_t *)malloc(sizeof(phHDLLCmdRsp_t));
1467     if (NULL == hdllCmdRsp) {
1468       ret = FW_DNLD_FAILURE;
1469       goto exit;
1470     }
1471     hdllCmdRsp->group = HCP_OPERATION_GROUP_GENERIC;
1472     hdllCmdRsp->operation = GENERIC_GROUP_OP_CODE_RESET;
1473     hdllCmdRsp->rsp_buf = rsp_buf;
1474     hdllCmdRsp->rsp_buf_len = rsp_buf_len;
1475     hdllCmdRsp->status = GENERIC_SUCCESS;
1476     hdllCmdRsp->type = HCP_TYPE_RESPONSE;
1477     ret = process_hdll_response(hdllCmdRsp);
1478   }
1479 exit:
1480   if (hdll_frame != NULL) {
1481     free(hdll_frame);
1482   }
1483   if (NULL != hdllCmd) {
1484     free(hdllCmd);
1485   }
1486   if (NULL != hdllCmdRsp) {
1487     free(hdllCmdRsp);
1488   }
1489   return ret;
1490 }
1491 
1492 /*******************************************************************************
1493 **
1494 ** Function    :   phGetEdlReadyNtf
1495 **
1496 ** Description :   This function frames the GetEdlReadyNtf command and sends to
1497                    the HeliosX chip
1498 **
1499 ** Parameters  :   None
1500 **
1501 ** Returns     :   FW_DNLD_FAILURE - If any failure occurs while framing or
1502                                     sending the command or while receiving the
1503                                     response
1504                    FW_DNLD_SUCCESS - On success
1505 **
1506 **
1507 *******************************************************************************/
phGetEdlReadyNtf()1508 phFWD_Status_t phGetEdlReadyNtf() {
1509   uint8_t rsp_buf[HDLL_READ_BUFF_SIZE] = {0};
1510   phFWD_Status_t ret = FW_DNLD_FAILURE;
1511   uint16_t rsp_buf_len = 0x0;
1512   phHDLLCmdRsp_t *hdllCmdRsp = NULL;
1513 
1514   NXPLOG_FWDNLD_D("Wait for EDL_READY notification\n");
1515   ret =
1516       phHdll_GetApdu((uint8_t *)&rsp_buf[0], HDLL_READ_BUFF_SIZE, &rsp_buf_len);
1517 
1518   if (!rsp_buf_len || ret == FW_DNLD_FAILURE) {
1519     NXPLOG_FWDNLD_D("Error in sending/receiving GET_EDL_READY cmd/response\n");
1520     return ret;
1521   }
1522 
1523   hdllCmdRsp = (phHDLLCmdRsp_t *)malloc(sizeof(phHDLLCmdRsp_t));
1524   if (NULL == hdllCmdRsp) {
1525     return ret;
1526   }
1527 
1528   hdllCmdRsp->group = HCP_OPERATION_GROUP_PROTOCOL;
1529   hdllCmdRsp->operation = PROTOCOL_GROUP_OP_CODE_EDL;
1530   hdllCmdRsp->rsp_buf = rsp_buf;
1531   hdllCmdRsp->rsp_buf_len = rsp_buf_len;
1532   hdllCmdRsp->status = READY;
1533   hdllCmdRsp->type = HCP_TYPE_NOTIFICATION;
1534   ret = process_hdll_response(hdllCmdRsp);
1535 
1536   if (NULL != hdllCmdRsp) {
1537     free(hdllCmdRsp);
1538   }
1539   return ret;
1540 }
1541 
1542 /*******************************************************************************
1543 **
1544 ** Function    :   phGenericGetInfo
1545 **
1546 ** Description :   This function frames the GenericGetInfo command and sends to
1547                    the HeliosX chip
1548 **
1549 ** Parameters  :   None
1550 **
1551 ** Returns     :   FW_DNLD_FAILURE - If any failure occurs while framing or
1552                                     sending the command or while receiving the
1553                                     response
1554                    FW_DNLD_SUCCESS - On success
1555 **
1556 **
1557 *******************************************************************************/
phGenericGetInfo()1558 phFWD_Status_t phGenericGetInfo() {
1559   uint8_t rsp_buf[HDLL_READ_BUFF_SIZE] = {0};
1560   uint8_t *hdll_frame = NULL;
1561   phFWD_Status_t ret = FW_DNLD_FAILURE;
1562   uint16_t rsp_buf_len = 0x0;
1563   phHDLLCmd_t *hdllCmd = NULL;
1564   phHDLLCmdRsp_t *hdllCmdRsp = NULL;
1565 
1566   hdllCmd = (phHDLLCmd_t *)malloc(sizeof(phHDLLCmd_t));
1567   if (NULL == hdllCmd) {
1568     ret = FW_DNLD_FAILURE;
1569     goto exit;
1570   }
1571   hdllCmd->group = HCP_OPERATION_GROUP_GENERIC;
1572   hdllCmd->operation = GENERIC_GROUP_OP_CODE_GETINFO;
1573   hdllCmd->chunk_size = 0;
1574   hdllCmd->frame_size = 0;
1575   hdllCmd->payload = NULL;
1576   hdllCmd->payload_len = 0;
1577 
1578   hdll_frame = phBuildHdllCmd(hdllCmd);
1579   if (NULL == hdll_frame) {
1580     goto exit;
1581   }
1582   NXPLOG_FWDNLD_D("Sending operation: OP_GENERIC_GET_INFO\n");
1583   ret = phGenericSendAndRecv(hdll_frame, hdllCmd->frame_size, rsp_buf,
1584                              &rsp_buf_len);
1585   if (!rsp_buf_len || ret == FW_DNLD_FAILURE) {
1586     NXPLOG_FWDNLD_D("Error in sending/receiving hdll cmd/response\n");
1587     return ret;
1588   }
1589 
1590   hdllCmdRsp = (phHDLLCmdRsp_t *)malloc(sizeof(phHDLLCmdRsp_t));
1591   if (NULL == hdllCmdRsp) {
1592     ret = FW_DNLD_FAILURE;
1593     goto exit;
1594   }
1595   hdllCmdRsp->group = HCP_OPERATION_GROUP_GENERIC;
1596   hdllCmdRsp->operation = GENERIC_GROUP_OP_CODE_GETINFO;
1597   hdllCmdRsp->rsp_buf = rsp_buf;
1598   hdllCmdRsp->rsp_buf_len = rsp_buf_len;
1599   hdllCmdRsp->status = GENERIC_SUCCESS;
1600   hdllCmdRsp->type = HCP_TYPE_RESPONSE;
1601   ret = process_hdll_response(hdllCmdRsp);
1602 exit:
1603   if (NULL != hdll_frame) {
1604     free(hdll_frame);
1605   }
1606   if (NULL != hdllCmd) {
1607     free(hdllCmd);
1608   }
1609   if (NULL != hdllCmdRsp) {
1610     free(hdllCmdRsp);
1611   }
1612   return ret;
1613 }
1614 
1615 /*******************************************************************************
1616 **
1617 ** Function    :   phHdll_GetHdllReadyNtf
1618 **
1619 ** Description :   This function frames the GetHdllReadyNtf command and sends to
1620                    the HeliosX chip
1621 **
1622 ** Parameters  :   None
1623 **
1624 ** Returns     :   FW_DNLD_FAILURE - If any failure occurs while framing or
1625                                     sending the command or while receiving the
1626                                     response
1627                    FW_DNLD_SUCCESS - On success
1628 **
1629 **
1630 *******************************************************************************/
phHdll_GetHdllReadyNtf()1631 phFWD_Status_t phHdll_GetHdllReadyNtf() {
1632   uint8_t rsp_buf[HDLL_READ_BUFF_SIZE] = {0};
1633   phFWD_Status_t ret = FW_DNLD_FAILURE;
1634   uint16_t rsp_buf_len = 0x0;
1635   phHDLLCmdRsp_t *hdllCmdRsp = NULL;
1636 
1637   NXPLOG_FWDNLD_D("Wait for HDL_READY notification\n");
1638   ret =
1639       phHdll_GetApdu((uint8_t *)&rsp_buf[0], HDLL_READ_BUFF_SIZE, &rsp_buf_len);
1640 
1641   if (!rsp_buf_len || ret == FW_DNLD_FAILURE) {
1642     NXPLOG_FWDNLD_D("Error in reading GET_HDL_READY notification\n");
1643     return ret;
1644   }
1645 
1646   hdllCmdRsp = (phHDLLCmdRsp_t *)malloc(sizeof(phHDLLCmdRsp_t));
1647   if (NULL == hdllCmdRsp) {
1648     return ret;
1649   }
1650 
1651   hdllCmdRsp->group = HCP_OPERATION_GROUP_PROTOCOL;
1652   hdllCmdRsp->operation = PROTOCOL_GROUP_OP_CODE_HDLL;
1653   hdllCmdRsp->rsp_buf = rsp_buf;
1654   hdllCmdRsp->rsp_buf_len = rsp_buf_len;
1655   hdllCmdRsp->status = READY;
1656   hdllCmdRsp->type = HCP_TYPE_NOTIFICATION;
1657   ret = process_hdll_response(hdllCmdRsp);
1658 
1659   if (FW_DNLD_SUCCESS != ret) {
1660     // check whether we received EDL ready notification or not
1661     // if yes, perform FW download directly.
1662     hdllCmdRsp->group = HCP_OPERATION_GROUP_PROTOCOL;
1663     hdllCmdRsp->operation = PROTOCOL_GROUP_OP_CODE_EDL;
1664     hdllCmdRsp->rsp_buf = rsp_buf;
1665     hdllCmdRsp->rsp_buf_len = rsp_buf_len;
1666     hdllCmdRsp->status = READY;
1667     hdllCmdRsp->type = HCP_TYPE_NOTIFICATION;
1668     ret = process_hdll_response(hdllCmdRsp);
1669 
1670     if (FW_DNLD_SUCCESS == ret) {
1671       bSkipEdlCheck = true;
1672     }
1673   }
1674 
1675   if (NULL != hdllCmdRsp) {
1676     free(hdllCmdRsp);
1677   }
1678 
1679   return ret;
1680 }
1681 
1682 /*******************************************************************************
1683 **
1684 ** Function    :   phEdl_send_and_recv
1685 **
1686 ** Description :   This function sends and receives the EDL group commands and
1687                    responses based on the given operation code.
1688 **
1689 ** Parameters  :   hdll_data - HDLL command buffer
1690                    hdll_data_len - HDLL command buffer len
1691                    group - HCP group code
1692                    operation - operation code.
1693 **
1694 ** Returns     :   FW_DNLD_FAILURE - If any failure occurs while framing or
1695                                     sending the command or while receiving the
1696                                     response
1697                    FW_DNLD_SUCCESS - On success
1698 **
1699 **
1700 *******************************************************************************/
1701 
phEdl_send_and_recv(uint8_t * hdll_data,uint32_t hdll_data_len,uint8_t group,uint8_t operation)1702 phFWD_Status_t phEdl_send_and_recv(uint8_t *hdll_data, uint32_t hdll_data_len,
1703                                    uint8_t group, uint8_t operation) {
1704   phFWD_Status_t ret = FW_DNLD_FAILURE;
1705   uint8_t rsp_buff[HDLL_READ_BUFF_SIZE] = {0};
1706 
1707   if (group != HCP_OPERATION_GROUP_EDL) {
1708     NXPLOG_FWDNLD_D("Error! HCP operation group is not EDL\n");
1709     return ret;
1710   }
1711   switch (operation) {
1712   case EDL_DOWNLOAD_CERTIFICATE: {
1713     ret = sendEdlDownloadCertificateCmd(hdll_data, hdll_data_len, rsp_buff);
1714   } break;
1715   case EDL_DOWNLOAD_FLASH_WRITE_FIRST: {
1716     ret = sendEdlFlashWriteFirstCmd(hdll_data, hdll_data_len, rsp_buff);
1717   } break;
1718   case EDL_DOWNLOAD_FLASH_WRITE: {
1719     ret = sendEdlFlashWriteCmd(hdll_data, hdll_data_len, rsp_buff);
1720   } break;
1721   case EDL_DOWNLOAD_FLASH_WRITE_LAST: {
1722     ret = sendEdlFlashWriteLastCmd(hdll_data, hdll_data_len, rsp_buff);
1723   } break;
1724   case EDL_LIFECYCLE_CERTIFICATE: {
1725     ret = sendEdlLifecycleCertificateCmd(hdll_data, hdll_data_len, rsp_buff);
1726   } break;
1727   case EDL_LIFECYCLE_WRITE_FIRST: {
1728     ret = sendEdlLifecycleWriteFirstCmd(hdll_data, hdll_data_len, rsp_buff);
1729   } break;
1730   case EDL_LIFECYCLE_WRITE_LAST: {
1731     ret = sendEdlLifecycleWriteLastCmd(hdll_data, hdll_data_len, rsp_buff);
1732   } break;
1733   case EDL_PATCH_FLASH_WRITE: {
1734     ret = sendEdlPatchFlashWriteCmd(hdll_data, hdll_data_len, rsp_buff);
1735   } break;
1736 
1737   default:
1738     break;
1739   }
1740   return ret;
1741 }
1742 
1743 /*******************************************************************************
1744 **
1745 ** Function    :   phLoadFwBinary
1746 **
1747 ** Description :   This function reads the MW FW binary file and writes to
1748                    HeliosX chip.
1749 **
1750 ** Parameters  :   pfwImageCtx -> pointer to fw image context
1751 **
1752 ** Returns     :   FW_DNLD_FAILURE - on failure
1753                    FW_DNLD_SUCCESS - On success
1754 **
1755 **
1756 *******************************************************************************/
phLoadFwBinary(phUwbFWImageContext_t * pfwImageCtx)1757 phFWD_Status_t phLoadFwBinary(phUwbFWImageContext_t *pfwImageCtx) {
1758   uint32_t next_frame_first_byte_index = 0;
1759   uint8_t current_op_group;
1760   uint8_t current_op;
1761   uint32_t frame_payload_length = 0;
1762   uint32_t frame_length = 0;
1763   phFWD_Status_t status = FW_DNLD_FAILURE;
1764   uint8_t current_frame[MAX_FRAME_LEN] = {0};
1765 
1766   if (NULL == pfwImageCtx->fwImage) {
1767     return status;
1768   }
1769   NXPLOG_FWDNLD_D("phLoadFwBinary\n");
1770   while (1) {
1771     // compute next frame payload length
1772     // TODO: warning this is not HDLL fragmentation compatible (valid header can
1773     // have chunk flag (biy 10 (13)) set) Assuming header length is 2 bytes
1774     frame_payload_length = (pfwImageCtx->fwImage[next_frame_first_byte_index] << 8) +
1775                            (pfwImageCtx->fwImage[next_frame_first_byte_index + 1]);
1776 
1777     // if max_payload_length is not None and (frame_payload_length >=
1778     // max_payload_length): raise Exception('Invalid SFWU content (not an HDLL
1779     // header).')
1780 
1781     // copy the header, the payload and the footer (crc) from the file bytes
1782     // into a byte array
1783     frame_length = frame_payload_length + HDLL_HEADER_LEN + HDLL_FOOTER_LEN;
1784     if (frame_length > MAX_FRAME_LEN) {
1785       NXPLOG_FWDNLD_E("%s: Error while performing FW download frame_length > "
1786                       "MAX_FRAME_LEN\n",
1787                       __func__);
1788       status = FW_DNLD_FAILURE;
1789       break;
1790     }
1791     memcpy(current_frame, &pfwImageCtx->fwImage[next_frame_first_byte_index],
1792            frame_length);
1793     current_op_group = current_frame[2];
1794     current_op = current_frame[3];
1795 
1796     status = phEdl_send_and_recv(current_frame, frame_length, current_op_group,
1797                                  current_op);
1798     if (status != FW_DNLD_SUCCESS) {
1799       NXPLOG_FWDNLD_E("%s: Error while performing FW download\n", __func__);
1800       break;
1801     }
1802 
1803     // update byte index
1804     next_frame_first_byte_index = next_frame_first_byte_index + frame_length;
1805 
1806     // check end of file
1807     if (next_frame_first_byte_index >= pfwImageCtx->fwImgSize) {
1808       break;
1809     }
1810   }
1811 
1812   // clean-up
1813   if (pfwImageCtx->fwImage != NULL) {
1814     if (pfwImageCtx->fw_dnld_config == BIN_FILE_BASED_FW_DOWNLOAD) {
1815       free(pfwImageCtx->fwImage);
1816     } else if (pfwImageCtx->fw_dnld_config == SO_FILE_BASED_FW_DOWNLOAD) {
1817       if (pfwImageCtx->gFwLib != NULL) {
1818         dlclose(pfwImageCtx->gFwLib);
1819         pfwImageCtx->gFwLib = NULL;
1820       }
1821     }
1822 
1823     pfwImageCtx->fwImage = NULL;
1824   }
1825   return status;
1826 }
1827 
1828 /******************************************************************************
1829  * Function         phHandle_hdll_read_timeout_cb
1830  *
1831  * Description      Timer call back function
1832  *
1833  * Returns          None
1834  *
1835  ******************************************************************************/
phHandle_hdll_read_timeout_cb(uint32_t timerId,void * pContext)1836 static void phHandle_hdll_read_timeout_cb(uint32_t timerId, void *pContext) {
1837   UNUSED(timerId);
1838   UNUSED(pContext);
1839   NXPLOG_FWDNLD_E("ERROR: phHandle_hdll_read_timeout_cb - HDLL read timeout\n");
1840   ioctl((intptr_t)tPalConfig.pDevHandle, SRXXX_SET_PWR, ABORT_READ_PENDING);
1841   isHdllReadTmeoutExpired = true;
1842 }
1843 
1844 /******************************************************************************/
1845 /*   GLOBAL FUNCTIONS                                                         */
1846 /******************************************************************************/
1847 
1848 /*******************************************************************************
1849 **
1850 ** Function    :   phHdll_GetApdu
1851 **
1852 ** Description :   This function reads the HDLL command's response from HeliosX
1853                    chip over SPI.
1854 **
1855 ** Parameters  :   pApdu     - HDLL response buffer
1856                    sz        - Max buffer size to be read
1857                    rsp_buf_len - HDLL response buffer length
1858 **
1859 ** Returns     :   phFWD_Status_t : 0 - success
1860                                      1 - failure
1861 **
1862 **
1863 *******************************************************************************/
1864 
phHdll_GetApdu(uint8_t * pApdu,uint16_t sz,uint16_t * rsp_buf_len)1865 phFWD_Status_t phHdll_GetApdu(uint8_t *pApdu, uint16_t sz,
1866                               uint16_t *rsp_buf_len) {
1867   // NXPLOG_FWDNLD_D("phHdll_GetApdu Enter\n");
1868   int ret_len = 0;
1869   int status = 0;
1870 
1871   if (sz == 0 || sz > PHHDLL_MAX_LEN_PAYLOAD_MISO) {
1872     NXPLOG_FWDNLD_E("ERROR: phHdll_GetApdu data len is 0 or greater than max "
1873                     "palyload length supported\n");
1874     return FW_DNLD_FAILURE;
1875   }
1876 
1877   /* Start timer */
1878   status = phOsalUwb_Timer_Start(timeoutTimerId, HDLL_READ_OP_TIMEOUT,
1879                                  &phHandle_hdll_read_timeout_cb, NULL);
1880   if (UWBSTATUS_SUCCESS != status) {
1881     NXPLOG_FWDNLD_E("%s: Response timer not started!!!", __func__);
1882     return FW_DNLD_FAILURE;
1883   }
1884   ret_len = read((intptr_t)tPalConfig.pDevHandle, (void *)pApdu, (sz));
1885 
1886   if (true == isHdllReadTmeoutExpired) {
1887     isHdllReadTmeoutExpired = false;
1888     return FW_DNLD_FAILURE;
1889   } else {
1890     /* Stop Timer */
1891     status = phOsalUwb_Timer_Stop(timeoutTimerId);
1892     if (UWBSTATUS_SUCCESS != status) {
1893       NXPLOG_FWDNLD_E("%s: Response timer stop ERROR!!!", __func__);
1894       return FW_DNLD_FAILURE;
1895     }
1896   }
1897 
1898   if (ret_len <= 0) {
1899     NXPLOG_FWDNLD_E("ERROR: Get APDU %u bytes failed!\n", sz);
1900     return FW_DNLD_FAILURE;
1901   }
1902   *rsp_buf_len = ret_len;
1903   if (is_fw_download_log_enabled == 0x01) {
1904     phNxpUciHal_print_packet(NXP_TML_FW_DNLD_RSP_UWBS_2_AP, pApdu, ret_len);
1905   }
1906 
1907   return FW_DNLD_SUCCESS;
1908 }
1909 
1910 /*******************************************************************************
1911 **
1912 ** Function    :   phHdll_PutApdu
1913 **
1914 ** Description :   This function sends the HDLL command to HeliosX chip over SPI
1915 **
1916 ** Parameters  :   pApdu     - HDLL command to be sent
1917                    sz        - HDLL command length
1918 **
1919 ** Returns     :   phFWD_Status_t : 0 - success
1920                                      1 - failure
1921 **
1922 **
1923 *******************************************************************************/
1924 
phHdll_PutApdu(uint8_t * pApdu,uint16_t sz)1925 phFWD_Status_t phHdll_PutApdu(uint8_t *pApdu, uint16_t sz) {
1926   int ret;
1927   int numWrote = 0;
1928   if (is_fw_download_log_enabled == 0x01) {
1929     phNxpUciHal_print_packet(NXP_TML_FW_DNLD_CMD_AP_2_UWBS, pApdu, sz);
1930   }
1931 
1932   ret = write((intptr_t)tPalConfig.pDevHandle, pApdu, sz);
1933   if (ret > 0) {
1934     numWrote += ret;
1935   } else if (ret == 0) {
1936     NXPLOG_FWDNLD_E("_spi_write() EOF");
1937     return FW_DNLD_FAILURE;
1938   } else {
1939     NXPLOG_FWDNLD_E("_spi_write() errno : %x", ret);
1940     return FW_DNLD_FAILURE;
1941   }
1942   return FW_DNLD_SUCCESS;
1943 }
1944 
1945 /*******************************************************************************
1946  * Function         hdll_fw_download
1947  *
1948  * Description      This function is called by jni when wired mode is
1949  *                  performed.First SRXXX driver will give the access
1950  *                  permission whether wired mode is allowed or not
1951  *                  arg (0):
1952  * Returns          FW_DNLD_SUCCESS - on success
1953                     FW_DNLD_FAILURE - on failure
1954                     FW_DNLD_FILE_NOT_FOUND - if the FW binary is not found or
1955                                              unable to open
1956  *
1957  ******************************************************************************/
hdll_fw_download()1958 int hdll_fw_download()
1959 {
1960   phFWD_Status_t ret = FW_DNLD_FAILURE;
1961   unsigned long num = 0;
1962   NXPLOG_FWDNLD_D("hdll_fw_download enter.....\n");
1963 
1964   isHdllReadTmeoutExpired = false;
1965   bSkipEdlCheck = false;
1966   if (NxpConfig_GetNum(NAME_UWB_FW_DOWNLOAD_LOG, &num, sizeof(num))) {
1967     is_fw_download_log_enabled = (uint8_t)num;
1968     ALOGD("NAME_UWB_FW_DOWNLOAD_LOG: 0x%02x\n", is_fw_download_log_enabled);
1969   } else {
1970     ALOGD("NAME_UWB_FW_DOWNLOAD_LOG: failed 0x%02x\n",
1971           is_fw_download_log_enabled);
1972   }
1973   ioctl((intptr_t)tPalConfig.pDevHandle, SRXXX_SET_FWD, PWR_ENABLE);
1974 
1975   ret = phHdll_GetHdllReadyNtf();
1976   if (ret != FW_DNLD_SUCCESS) {
1977     NXPLOG_FWDNLD_E("%s:%d error in getting the hdll ready notification...\n",
1978                     __func__,__LINE__);
1979     return ret;
1980   }
1981   /* Get the Device information */
1982   ret = phGenericGetInfo();
1983   if (ret == FW_DNLD_FILE_NOT_FOUND) {
1984       goto exit;
1985   }
1986 
1987   if (ret == FW_DNLD_FAILURE) {
1988     NXPLOG_FWDNLD_E("%s: error in getting the getInfo notification...\n",
1989                       __func__);
1990     return ret;
1991   }
1992 
1993   if (!bSkipEdlCheck) {
1994     if (ret == FW_DNLD_NOT_REQUIRED)
1995     {
1996       goto exit;
1997     }
1998     ret = phGetEdlReadyNtf();
1999     if (ret != FW_DNLD_SUCCESS) {
2000       NXPLOG_FWDNLD_E("%s: error in getting the EDL ready notification...\n",
2001                       __func__);
2002       return ret;
2003     }
2004   }
2005 
2006   if(fwImageCtx.fwRecovery)
2007   {
2008     /* perform FW recovery */
2009     ret = phNxpUciHal_fw_recovery(&fwImageCtx);
2010     if (ret == FW_DNLD_FAILURE) {
2011       NXPLOG_FWDNLD_E("%s: error downloading recovery FW...\n",
2012                       __func__);
2013       return ret;
2014     }
2015     // TODO: Remove this after recovrry FW tested added to avoid endless loop of fw download.
2016     fwImageCtx.fwRecovery = false;
2017   }
2018 
2019   /*  */
2020   ret = phLoadFwBinary(&fwImageCtx);
2021   if (ret != FW_DNLD_SUCCESS) {
2022     NXPLOG_FWDNLD_E("%s: error in phLoadFwBinary...\n", __func__);
2023     return ret;
2024   }
2025 
2026 exit:
2027   // do chip reset
2028   phTmlUwb_Chip_Reset();
2029   ret = phHdll_GetHdllReadyNtf();
2030 
2031   ioctl((intptr_t)tPalConfig.pDevHandle, SRXXX_SET_FWD, PWR_DISABLE);
2032   NXPLOG_FWDNLD_D("hdll_fw_download completed.....\n");
2033   return ret;
2034 }
2035 
2036 /*******************************************************************************
2037  * Function         phNxpUciHal_fw_recovery
2038  *
2039  * Description      This function is use to download recovery FW
2040  * Returns          FW_DNLD_SUCCESS - on success
2041                     FW_DNLD_FAILURE - on failure
2042                     FW_DNLD_FILE_NOT_FOUND - if the FW binary is not found or
2043                                              unable to open
2044  *
2045  ******************************************************************************/
2046 
phNxpUciHal_fw_recovery(phUwbFWImageContext_t * pfwImageCtx)2047 static phFWD_Status_t phNxpUciHal_fw_recovery(phUwbFWImageContext_t *pfwImageCtx) {
2048   phFWD_Status_t ret = FW_DNLD_FAILURE;
2049   NXPLOG_FWDNLD_D("phNxpUciHal_fw_recovery enter.....\n");
2050 
2051   ret = phLoadFwBinary(pfwImageCtx);
2052   if (ret != FW_DNLD_SUCCESS) {
2053     NXPLOG_FWDNLD_E("%s: error in phLoadFwBinary...\n", __func__);
2054     return ret;
2055   }
2056 
2057   // do chip reset
2058   phTmlUwb_Chip_Reset();
2059   ret = phHdll_GetHdllReadyNtf();
2060   if (ret != FW_DNLD_SUCCESS) {
2061     NXPLOG_FWDNLD_E("%s:%d error in getting the hdll ready notification...\n",
2062                     __func__,__LINE__);
2063     return ret;
2064   }
2065   /* Get the Device information */
2066   ret = phGenericGetInfo();
2067   if (ret == FW_DNLD_FAILURE || ret == FW_DNLD_FILE_NOT_FOUND) {
2068       NXPLOG_FWDNLD_E("%s:%d error in getting the getInfo notification...\n",
2069                       __func__,__LINE__);
2070       return ret;
2071   }
2072 
2073   if (!bSkipEdlCheck) {
2074     if (ret == FW_DNLD_NOT_REQUIRED) {
2075       return ret;
2076     }
2077 
2078     ret = phGetEdlReadyNtf();
2079     if (ret != FW_DNLD_SUCCESS) {
2080       NXPLOG_FWDNLD_E("%s:%d error in getting the EDL ready notification...\n",
2081                       __func__,__LINE__);
2082       return ret;
2083     }
2084   }
2085 
2086   return ret;
2087 }
2088 
2089 /*******************************************************************************
2090  * Function         phNxpUciHal_fw_lcrotation
2091  *
2092  * Description      This function is use to download recovery FW
2093  * Returns          FW_DNLD_SUCCESS - on success
2094                     FW_DNLD_FAILURE - on failure
2095                     FW_DNLD_FILE_NOT_FOUND - if the FW binary is not found or
2096                                              unable to open
2097  *
2098  ******************************************************************************/
2099 
phNxpUciHal_fw_lcrotation()2100 phFWD_Status_t phNxpUciHal_fw_lcrotation() {
2101   phFWD_Status_t ret = FW_DNLD_FAILURE;
2102   glcRotation = true;
2103   NXPLOG_FWDNLD_D("phNxpUciHal_fw_lcrotation enter.....\n");
2104 
2105   ioctl((intptr_t)tPalConfig.pDevHandle, SRXXX_SET_FWD, PWR_ENABLE);
2106 
2107   ret = phHdll_GetHdllReadyNtf();
2108   if (ret != FW_DNLD_SUCCESS) {
2109     NXPLOG_FWDNLD_E("%s:%d error in getting the hdll ready notification...\n",
2110                     __func__,__LINE__);
2111     return ret;
2112   }
2113     /* Get the Device information */
2114   ret = phGenericGetInfo();
2115   if (ret == FW_DNLD_FILE_NOT_FOUND) {
2116     goto exit;
2117   }
2118 
2119   if (ret == FW_DNLD_FAILURE) {
2120       NXPLOG_FWDNLD_E("%s:%d error in getting the getInfo notification...\n",
2121                       __func__,__LINE__);
2122       return ret;
2123   }
2124 
2125   if (!bSkipEdlCheck) {
2126 
2127     ret = phGetEdlReadyNtf();
2128     if (ret != FW_DNLD_SUCCESS) {
2129       NXPLOG_FWDNLD_E("%s:%d error in getting the EDL ready notification...\n",
2130                       __func__,__LINE__);
2131       return ret;
2132     }
2133   }
2134   ret = phLoadFwBinary(&fwImageCtx);
2135   if (ret != FW_DNLD_SUCCESS) {
2136     NXPLOG_FWDNLD_E("%s: error in phLoadFwBinary...\n", __func__);
2137     glcRotation = false;
2138     return ret;
2139   }
2140   glcRotation = false;
2141 
2142 exit:
2143   // do chip reset
2144   phTmlUwb_Chip_Reset();
2145   ret = phHdll_GetHdllReadyNtf();
2146 
2147   ioctl((intptr_t)tPalConfig.pDevHandle, SRXXX_SET_FWD, PWR_DISABLE);
2148   NXPLOG_FWDNLD_D("hdll_fw_download completed.....\n");
2149   return ret;
2150 }
2151 
2152 /*******************************************************************************
2153  * Function         setDeviceHandle
2154  *
2155  * Description      This function sets the SPI device handle that needs to be
2156                     used in this file for SPI communication
2157  * Parameters       pDevHandle - SPI device handle
2158  * Returns          None
2159  *
2160  ******************************************************************************/
setDeviceHandle(void * pDevHandle)2161 void setDeviceHandle(void *pDevHandle) {
2162   NXPLOG_FWDNLD_D("Set the device handle!\n");
2163   if (pDevHandle == NULL) {
2164     NXPLOG_FWDNLD_E("device handle is NULL!\n");
2165   } else {
2166     tPalConfig.pDevHandle = (void *)((intptr_t)pDevHandle);
2167   }
2168 }
2169