1 /*
2  * Copyright 2024 NXP
3  * All rights reserved.
4  *
5  * SPDX-License-Identifier: BSD-3-Clause
6  *
7  */
8 
9 #include <stdint.h>
10 #include <stdio.h>
11 #include <string.h>
12 #include "fsl_loader_utils.h"
13 #include "api_tree_root.h"
14 #include "fsl_power.h"
15 #ifndef __ZEPHYR__
16 #include "board.h"
17 #include "fsl_debug_console.h"
18 #else
19 #include "fsl_clock.h"
20 #endif
21 
22 #ifdef MCUBOOT_APPLICATION
23 #include "mcuboot_app_support.h"
24 #endif
25 
26 #include "mflash_drv.h"
27 
28 #if defined(MBEDTLS_THREADING_C) && defined(MBEDTLS_THREADING_ALT)
29 #if defined(PSA_CRYPTO_DRIVER_THREAD_EN)
30 #include "mcux_psa_els_pkc_common_init.h"
31 #else
32 #include "els_pkc_mbedtls.h"
33 #endif /* defined(PSA_CRYPTO_DRIVER_THREAD_EN) */
34 #endif /* defined(MBEDTLS_THREADING_C) && defined(MBEDTLS_THREADING_ALT) */
35 
36 //! @addtogroup sbloader
37 //! @{
38 
39 /*******************************************************************************
40  * Definitions
41  ******************************************************************************/
42 #if 0
43 #define SBLOADER_PRINTF(...)     \
44     do                           \
45     {                            \
46         PLOG_DEBUG(__VA_ARGS__); \
47     } while (0)
48 #else
49 #define SBLOADER_PRINTF(...)
50 #endif
51 
52 /*!
53  * @brief load cpu1/cpu2 firmware.
54  */
55 #define CIU_RST_SW2                (0x41240184U)
56 #define CIU_RST_SW2_CPU1_RST_MASK  (0x40000000U)
57 #define CIU2_RST_SW3               (0x4424011cU)
58 #define CIU2_RST_SW3_CPU2_RST_MASK (0x00000010U)
59 
60 #define IMU_SYNC_MAGIC_PATTERN  (0xABCDEF89U)
61 #define CPU1_MAGIC_PATTERN_ADDR (0x41380000U)
62 #define CPU2_MAGIC_PATTERN_ADDR (0x443c0000U)
63 
64 #define SOCCTRL_CHIP_INFO_REV_NUM_MASK (0xFU)
65 
66 
67 #define CLKCTL0_PSCCTL1_OTP_MASK  (0x20000U)
68 #define RSTCTL0_PRSTCTL1_OTP_MASK (0x20000U)
69 
70 #define STAGING_BUF_SZ 256u
71 typedef struct sb3_desc {
72     uint32_t fmt;
73     uint32_t sub_fmt;
74     uint32_t dst_addr;
75     uint32_t area_sz;
76 } sb3_load_desc_t;
77 
78 /*******************************************************************************
79  * Prototype
80  ******************************************************************************/
81 static status_t ldr_DoHeader_v3(fsl_api_core_context_t *ctx);
82 static status_t ldr_DoDataRead(fsl_api_core_context_t *ctx);
83 static status_t ldr_DoBlock(fsl_api_core_context_t *ctx);
84 static status_t ldr_DoLoadCmd(fsl_api_core_context_t *ctx);
85 static status_t ldr_DoExecuteCmd(fsl_api_core_context_t *ctx);
86 static status_t ldr_ReadFromFlash(uint8_t * buf, uint32_t src_flash_offset, size_t read_sz);
87 
88 static status_t load_service_monolithic(LOAD_Target_Type loadTarget, uint32_t sourceAddr);
89 
90 /*******************************************************************************
91  * Variables
92  ******************************************************************************/
93 /*! @brief nboot library context. */
94 static fsl_api_core_context_t s_fsl_api_core_context = {0};
95 static fsl_ldr_Context_v3_t s_sbloader_context;
96 static uint8_t packetBuf[512]  = {0};
97 static fsl_nboot_context_t g_nbootCtx = {0};
98 #ifdef CONFIG_FW_VDLLV2
99 static uint32_t vdll_image_base = 0;
100 #endif
101 
102 static bootloader_tree_v0_t *g_bootloaderTree_v0;
103 static bootloader_tree_v1_t *g_bootloaderTree_v1;
104 
105 /*******************************************************************************
106  * Codes
107  ******************************************************************************/
108 __attribute__((__noinline__))
sb3_Delay(uint32_t loop)109 static void sb3_Delay(uint32_t loop)
110 {
111     if (loop > 0U)
112     {
113         __ASM volatile(
114             "1:                             \n"
115             "    SUBS   %0, %0, #1          \n"
116             "    CMP    %0, #0              \n"
117             "    BNE    1b                  \n"
118             :
119             : "r"(loop));
120     }
121 }
122 
sb3_DelayUs(uint32_t us)123 static void sb3_DelayUs(uint32_t us)
124 {
125     uint32_t instNum;
126 
127     instNum = ((SystemCoreClock + 999999UL) / 1000000UL) * us;
128     sb3_Delay((instNum + 2U) / 3U);
129 }
130 
_ActiveApplicationRemapOffset(void)131 static uint32_t _ActiveApplicationRemapOffset(void)
132 {
133     return (MFLASH_FLEXSPI->HADDROFFSET);
134 }
135 ////////////////////////////////////////////////////////////////////////////
136 //! @brief power on device implementation
137 ////////////////////////////////////////////////////////////////////////////
power_on_device_impl(LOAD_Target_Type loadTarget)138 void power_on_device_impl(LOAD_Target_Type loadTarget)
139 {
140     uint8_t target_type = ((uint8_t)loadTarget & ~0x80);
141 
142     if (LOAD_WIFI_FIRMWARE == target_type)
143     {
144         POWER_PowerOnWlan();
145     }
146     else if ((LOAD_BLE_FIRMWARE == target_type) || (LOAD_15D4_FIRMWARE == target_type))
147     {
148         POWER_PowerOnBle();
149     }
150     else
151     {
152         ; /* none to do */
153     }
154     // There's 2.6us gap from device Power-On till device sub-system power up.
155     // Do a time delay which >2.6us for device sub-system here.
156     sb3_DelayUs(5U);
157 }
158 
159 ////////////////////////////////////////////////////////////////////////////
160 //! @brief power off device implementation
161 ////////////////////////////////////////////////////////////////////////////
power_off_device_impl(LOAD_Target_Type loadTarget)162 void power_off_device_impl(LOAD_Target_Type loadTarget)
163 {
164     uint8_t target_type = ((uint8_t)loadTarget & ~0x80);
165 
166     if (LOAD_WIFI_FIRMWARE == target_type)
167     {
168         POWER_PowerOffWlan();
169     }
170     else if ((LOAD_BLE_FIRMWARE == target_type) || (LOAD_15D4_FIRMWARE == target_type))
171     {
172         POWER_PowerOffBle();
173     }
174     else
175     {
176         ; /* none to do */
177     }
178     sb3_DelayUs(5U);
179 }
180 
181 ////////////////////////////////////////////////////////////////////////////
182 //! @brief reset device
183 ////////////////////////////////////////////////////////////////////////////
reset_device(LOAD_Target_Type loadTarget)184 void reset_device(LOAD_Target_Type loadTarget)
185 {
186     uint8_t target_type = ((uint8_t)loadTarget & ~0x80);
187     if (LOAD_WIFI_FIRMWARE == target_type)
188     {
189         *((uint32_t *)CIU_RST_SW2) = *((uint32_t *)CIU_RST_SW2) | CIU_RST_SW2_CPU1_RST_MASK;
190     }
191     else if ((LOAD_BLE_FIRMWARE == target_type) || (LOAD_15D4_FIRMWARE == target_type))
192     {
193         *((uint32_t *)CIU2_RST_SW3) = *((uint32_t *)CIU2_RST_SW3) | CIU2_RST_SW3_CPU2_RST_MASK;
194     }
195     else
196     {
197         ; /* none to do */
198     }
199 }
200 
get_sbloader_v3_context(fsl_api_core_context_t * ctx)201 static fsl_ldr_Context_v3_t *get_sbloader_v3_context(fsl_api_core_context_t *ctx)
202 {
203     return ctx->sbloaderCtx;
204 }
205 
206 ////////////////////////////////////////////////////////////////////////////
207 //! @brief get firmware version from otp
208 ////////////////////////////////////////////////////////////////////////////
nboot_hal_get_secure_firmware_version(uint32_t * fwVer,LOAD_Target_Type loadTarget)209 static fsl_nboot_status_t nboot_hal_get_secure_firmware_version(uint32_t *fwVer, LOAD_Target_Type loadTarget)
210 {
211     if (fwVer == NULL)
212     {
213         return kStatus_NBOOT_InvalidArgument;
214     }
215 
216     uint32_t tmpVersion               = 0u;
217     uint32_t trustedFwVersionFuses[4] = {0};
218     uint32_t fuseIdxStart;
219 
220     uint8_t target_type = (uint8_t)loadTarget & ~0x80;
221      if (LOAD_WIFI_FIRMWARE == target_type)
222     {
223         fuseIdxStart = OTP_WIFI_FW_VER0_FUSE_IDX;
224     }
225     else if (LOAD_BLE_FIRMWARE == target_type)
226     {
227         fuseIdxStart = OTP_BLE_FW_VER0_FUSE_IDX;
228     }
229     else if (LOAD_15D4_FIRMWARE == target_type)
230     {
231         fuseIdxStart = OTP_15_4_FW_VER0_FUSE_IDX;
232     }
233     else
234     {
235         return kStatus_NBOOT_InvalidArgument;
236     }
237 
238     for (uint32_t i = 0u; i < ARRAY_SIZE(trustedFwVersionFuses); i++)
239     {
240         status_t status = OCOTP_OtpFuseRead(fuseIdxStart, &trustedFwVersionFuses[i]);
241         if (status != kStatus_Success)
242         {
243             return kStatus_NBOOT_Fail;
244         }
245         ++fuseIdxStart;
246     }
247 
248     for (uint32_t i = 0u; i < ARRAY_SIZE(trustedFwVersionFuses); i++)
249     {
250         // Only the low-half 16-bit is used for counter calculation
251         for (uint8_t j = 0U; j < 16U; j++)
252         {
253             if ((trustedFwVersionFuses[i] & (uint32_t)((uint32_t)(1U) << j)) != 0U)
254             {
255                 ++tmpVersion;
256             }
257         }
258     }
259 
260     *fwVer = tmpVersion;
261 
262     return kStatus_NBOOT_Success;
263 }
264 ////////////////////////////////////////////////////////////////////////////
265 //! @brief fw download implementation
266 ////////////////////////////////////////////////////////////////////////////
sb3_fw_download_impl(LOAD_Target_Type loadTarget,uint32_t flag,uint32_t sourceAddr)267 status_t sb3_fw_download_impl(LOAD_Target_Type loadTarget, uint32_t flag, uint32_t sourceAddr)
268 {
269     volatile uint32_t *magic_pattern_addr = NULL;
270     status_t status                       = kStatus_Fail;
271     int wait_count                        = 200;
272     uint8_t target_type                   = ((uint8_t)loadTarget & ~0x80);
273 
274     if ((g_bootloaderTree_v1 == NULL) && ((get_chip_revision() == 1U) || (get_chip_revision() == 2U)))
275     {
276         g_bootloaderTree_v1 = ((bootloader_tree_v1_t *)0x13030000);
277     }
278     else if (g_bootloaderTree_v0 == NULL)
279     {
280         g_bootloaderTree_v0 = ((bootloader_tree_v0_t *)0x13024100);
281     }
282 	else
283     {
284         ; /* none to do */
285     }
286 
287     if (LOAD_WIFI_FIRMWARE == target_type)
288     {
289         magic_pattern_addr = (volatile uint32_t *)CPU1_MAGIC_PATTERN_ADDR;
290     }
291     else if ((LOAD_BLE_FIRMWARE == target_type) || (LOAD_15D4_FIRMWARE == target_type))
292     {
293         magic_pattern_addr = (volatile uint32_t *)CPU2_MAGIC_PATTERN_ADDR;
294     }
295 #ifdef CONFIG_FW_VDLLV2
296     else if (LOAD_WIFI_VDLL_FIRMWARE == loadTarget)
297     {
298         status = load_service(loadTarget, sourceAddr);
299         return status;
300     }
301 #endif
302     else
303     {
304         return status;
305     }
306 
307     // Check if fw already active, if active skip download fw
308     if (IMU_SYNC_MAGIC_PATTERN == *((volatile uint32_t *)magic_pattern_addr))
309     {
310         status = kStatus_Success;
311         return status;
312     }
313 
314     if (loadTarget & 0x80)
315     {
316         status = load_service_monolithic(loadTarget, sourceAddr);
317     }
318     else
319     {
320         status = load_service(loadTarget, sourceAddr);
321     }
322 
323     // Wait for fw activation for 1s. Return fail if wait_count is used up.
324     while (wait_count != 0)
325     {
326         if (IMU_SYNC_MAGIC_PATTERN != *((volatile uint32_t *)magic_pattern_addr))
327         {
328             /* 5 ms delay */
329             sb3_DelayUs(1000 * 5);
330             wait_count--;
331             if (wait_count == 0)
332             {
333                 status = kStatus_Fail;
334             }
335         }
336         else
337         {
338             status = kStatus_Success;
339             break;
340         }
341     }
342 
343     return status;
344 }
345 
346 ////////////////////////////////////////////////////////////////////////////
347 //! @brief fw reset implementation
348 ////////////////////////////////////////////////////////////////////////////
sb3_fw_reset_impl(LOAD_Target_Type loadTarget,uint32_t flag,uint32_t sourceAddr)349 status_t sb3_fw_reset_impl(LOAD_Target_Type loadTarget, uint32_t flag, uint32_t sourceAddr)
350 {
351     status_t status = kStatus_Fail;
352 
353     power_off_device_impl(loadTarget);
354 
355     status = sb3_fw_download_impl(loadTarget, flag, sourceAddr);
356 
357     return status;
358 }
359 
360 ////////////////////////////////////////////////////////////////////////////
361 //! @brief load command processing
362 ////////////////////////////////////////////////////////////////////////////
ldr_DoLoadCmd(fsl_api_core_context_t * ctx)363 static status_t ldr_DoLoadCmd(fsl_api_core_context_t *ctx)
364 {
365     status_t status = kStatus_Fail;
366 
367     fsl_ldr_Context_v3_t *context = get_sbloader_v3_context(ctx);
368 
369     // check current data_block_position
370     if (context->data_block_position == context->block_data_size)
371     {
372         // we reached end of data section, need to get the next block
373         status = kStatus_Success;
374     }
375     else if (context->data_block_position + context->data_range_header.length <= context->block_data_size)
376     {
377         // the load data enough in data section (buffer)
378         (void)memcpy((uint8_t *)context->data_range_header.startAddress,
379                      (uint8_t *)&context->data_block[context->data_block_position], context->data_range_header.length);
380         // this load command completed.
381         // this data range section process finiskStatus_FLASH_Successhed.
382         context->in_data_range      = false;
383         context->data_range_handled = 0;
384         context->data_block_position += context->data_range_header.length + context->data_range_gap;
385         context->data_section_handled += context->data_range_header.length + context->data_range_gap;
386         status = kStatus_Success;
387     }
388     else
389     {
390         // we have partial data to load
391         (void)memcpy((uint8_t *)context->data_range_header.startAddress,
392                      (uint8_t *)&context->data_block[context->data_block_position],
393                      context->block_data_size - context->data_block_position);
394         context->data_range_handled = context->block_data_size - context->data_block_position;
395         context->data_range_header.startAddress += context->data_range_handled;
396         context->data_range_header.length -= context->data_range_handled;
397         context->data_block_position += context->data_range_handled;
398         context->data_section_handled += context->data_range_handled;
399         status = kStatus_Success;
400     }
401 
402     return status;
403 }
404 
405 ////////////////////////////////////////////////////////////////////////////
406 //! @brief Execute command processing
407 ////////////////////////////////////////////////////////////////////////////
ldr_DoExecuteCmd(fsl_api_core_context_t * ctx)408 static status_t ldr_DoExecuteCmd(fsl_api_core_context_t *ctx)
409 {
410     fsl_ldr_Context_v3_t *context = get_sbloader_v3_context(ctx);
411     // this data range section process finished.
412     context->in_data_range      = false;
413     context->data_range_handled = 0;
414 
415     // Actual jump is implemented in fsl_sbloader_finalize().
416     return (status_t)kStatusRomLdrPendingJumpCommand;
417 }
418 
419 ////////////////////////////////////////////////////////////////////////////
420 //! @brief data block processing
421 ////////////////////////////////////////////////////////////////////////////
ldr_DoBlock(fsl_api_core_context_t * ctx)422 static status_t ldr_DoBlock(fsl_api_core_context_t *ctx)
423 {
424     fsl_ldr_Context_v3_t *context = get_sbloader_v3_context(ctx);
425 
426     status_t status = kStatus_Fail;
427     // new data range with new data block
428     fsl_sb3_data_range_header_t *data_range_header;
429     fsl_sb3_section_header_t *data_section_header;
430 
431     while (context->in_data_block)
432     {
433         // check if we are in a data section
434         if (context->in_data_section)
435         {
436             // in process of a data section
437             data_section_header = &context->data_section_header;
438         }
439         else
440         {
441             // new data section started
442             data_section_header = (fsl_sb3_section_header_t *)(void *)&context->data_block[context->data_block_position];
443 
444             // save data range section header
445             (void)memcpy(&context->data_section_header, data_section_header, sizeof(fsl_sb3_section_header_t));
446 
447             // branch to section types (only data range is currently supported)
448             switch (data_section_header->sectionType)
449             {
450                 case ((uint32_t)kSectionNone):
451                     status = kStatus_Success;
452                     break;
453                 case ((uint32_t)kSectionDataRange):
454                     context->in_data_section      = true;
455                     context->data_section_handled = 0;
456                     context->in_data_range        = false;
457                     context->data_range_handled   = 0;
458                     context->data_block_position += sizeof(fsl_sb3_section_header_t);
459                     break;
460                 case ((uint32_t)kSectionDiffUpdate):
461                 case ((uint32_t)kSectionDDRConfig):
462                 case ((uint32_t)kSectionRegister):
463                 default:
464                     // non-supported section type
465                     SBLOADER_PRINTF("Bootloader: %s, invalid section type = %x", __func__,
466                                     data_section_header->sectionType);
467                     status = kStatus_Fail;
468                     break;
469             }
470             if (data_section_header->sectionType != (uint32_t)kSectionDataRange)
471             {
472                 return status;
473             }
474         }
475 
476         switch (data_section_header->sectionType)
477         {
478             case ((uint32_t)kSectionDataRange):
479             {
480                 // check if we are in a data range
481                 if (context->in_data_range)
482                 {
483                     // continue current data range process
484                     data_range_header = &context->data_range_header;
485                 }
486                 else
487                 {
488                     // started a new data range
489                     data_range_header =
490                         (fsl_sb3_data_range_header_t *)(void *)&context->data_block[context->data_block_position];
491 
492                     // check command tag
493                     if (data_range_header->tag != SB3_DATA_RANGE_HEADER_TAG)
494                     {
495                         // bad data range section
496                         status = kStatus_Fail;
497                         SBLOADER_PRINTF("Bootloader: %s, invalid data range header tag = %x", __func__,
498                                         data_range_header->tag);
499                         return status;
500                     }
501 
502                     // save data range section header
503                     (void)memcpy(&context->data_range_header, data_range_header, sizeof(fsl_sb3_data_range_header_t));
504                     context->in_data_range            = true;
505                     context->has_data_range_expansion = false;
506                     context->data_range_handled       = sizeof(fsl_sb3_data_range_header_t); // used anywhere?
507                     context->data_block_position += sizeof(fsl_sb3_data_range_header_t);
508                     context->data_section_handled += sizeof(fsl_sb3_data_range_header_t);
509 
510                     // 16 bytes alignmnent check and handling
511                     context->data_range_gap = 0;
512 
513                     switch ((fsl_sb3_cmd_t)data_range_header->cmd)
514                     {
515                         case kSB3_CmdLoad:
516                             context->data_range_gap =
517                                 (SB3_DATA_ALIGNMENT_SIZE_IN_BYTE - (data_range_header->length & 0xFU)) & 0xFU;
518                             break;
519                         default:
520                             // Do nothing for the commands.
521                             break;
522                     }
523                 }
524 
525                 switch (data_range_header->cmd)
526                 {
527                     case ((uint32_t)kSB3_CmdLoad):
528                         if (!context->has_data_range_expansion)
529                         {
530                             SBLOADER_PRINTF("Bootloader: %s, Copy data range expansion", __func__);
531                             // check current data_block_position
532                             if (context->data_block_position == context->block_data_size)
533                             {
534                                 // we reached end of data section, need to get the next block
535                                 return kStatus_Success;
536                             }
537                             else if ((context->data_block_position + sizeof(fsl_sb3_data_range_expansion_t)) <=
538                                      context->block_data_size)
539                             {
540                                 // save data range section header expansion.
541                                 (void)memcpy(&context->data_range_expansion,
542                                              (fsl_sb3_data_range_expansion_t *)&context
543                                                  ->data_block[context->data_block_position],
544                                              sizeof(fsl_sb3_data_range_expansion_t));
545                                 context->has_data_range_expansion = true;
546                                 context->data_block_position += sizeof(fsl_sb3_data_range_expansion_t);
547                                 context->data_section_handled += sizeof(fsl_sb3_data_range_expansion_t);
548                             }
549                             else
550                             {
551                                 // Unaligned data range.
552                                 return kStatus_Fail;
553                             }
554                         }
555                         else
556                         {
557                             SBLOADER_PRINTF("Bootloader: %s, Has data range expansion", __func__);
558                         }
559                         break;
560                     default:
561                         // Do nothing for the commands without header expansion.
562                         break;
563                 }
564 
565                 // branch to range commands
566                 switch (data_range_header->cmd)
567                 {
568                     case ((uint32_t)kSB3_CmdLoad):
569                         status = ldr_DoLoadCmd(ctx);
570                         if (status != kStatus_Success)
571                         {
572                             return status;
573                         }
574                         break;
575                     case ((uint32_t)kSB3_CmdExecute):
576                         status = ldr_DoExecuteCmd(ctx);
577                         break;
578                     default:
579                         // this data range section process finished.
580                         context->in_data_range      = false;
581                         context->data_range_handled = 0;
582                         break;
583                 }
584                 if (data_range_header->cmd == (uint32_t)kSB3_CmdExecute)
585                 {
586                     return status;
587                 }
588 
589                 // check if we reach the end of this data section
590                 if (context->data_section_handled == context->data_section_header.length)
591                 {
592                     // this data section completed
593                     context->in_data_section = false;
594                 }
595                 else if (context->data_section_handled > context->data_section_header.length)
596                 {
597                     // bad data section
598                     // return error
599                     SBLOADER_PRINTF("Bootloader: %s, bad data section.", __func__);
600                     status = kStatus_Fail;
601                     return status;
602                 }
603                 else
604                 {
605                     ; /* none to do */
606                 }
607 
608                 // check if we reach the end of this data block
609                 if (context->data_block_position == context->block_data_size)
610                 {
611                     // This data block process finished.
612                     context->block_buffer_position = 0;
613                     context->in_data_block         = false;
614                     context->data_block_position   = 0;
615                     context->Action                = (fsl_pLdrFnc_v3_t)ldr_DoDataRead;
616                     SBLOADER_PRINTF("Bootloader: %s, data blobck process done.", __func__);
617                     status = kStatus_Success;
618                 }
619                 else if (context->data_block_position > context->block_data_size)
620                 {
621                     // bad block position
622                     // bad pointer
623                     SBLOADER_PRINTF("Bootloader: %s, bad block position.", __func__);
624                     status = kStatus_Fail;
625                     return status;
626                 }
627                 else if (context->data_block_position + SB3_DATA_ALIGNMENT_SIZE_IN_BYTE > context->block_data_size)
628                 {
629                     // data is not 16 bytes aligned.
630                     // return error
631                     status = kStatus_Fail;
632                     SBLOADER_PRINTF("Bootloader: %s, data not aligned.", __func__);
633                     return status;
634                 }
635                 else
636                 {
637                     ; /* none to do */
638                 }
639             }
640             break;
641             case ((uint32_t)kSectionDiffUpdate):
642             case ((uint32_t)kSectionDDRConfig):
643             case ((uint32_t)kSectionRegister):
644             default:
645                 // non-supported section type
646                 SBLOADER_PRINTF("Bootloader: %s, non-supported section type = %x", __func__,
647                                 data_section_header->sectionType);
648                 status                 = kStatus_Fail;
649                 context->in_data_block = false;
650                 break;
651         }
652     }
653 
654     return status;
655 }
656 
657 ////////////////////////////////////////////////////////////////////////////
658 //! @brief data block decryption and handling
659 ////////////////////////////////////////////////////////////////////////////
ldr_DoDataRead(fsl_api_core_context_t * ctx)660 static status_t ldr_DoDataRead(fsl_api_core_context_t *ctx)
661 {
662     status_t status                = kStatus_Fail;
663     fsl_nboot_status_t nbootResult = kStatus_NBOOT_Fail;
664 
665     fsl_ldr_Context_v3_t *context = get_sbloader_v3_context(ctx);
666 
667     // check block integrity
668     if (context->processedBlocks < ctx->nbootCtx->totalBlocks)
669     {
670         // call nboot lib to decrypt the data block
671         if ((get_chip_revision() == 1U) || (get_chip_revision() == 2U))
672         {
673             nbootResult = (fsl_nboot_status_t)g_bootloaderTree_v1->nbootDriver->nboot_sb3_load_block(
674                 ctx->nbootCtx, (uint32_t *)&context->block_buffer[0]);
675         }
676         else
677         {
678             nbootResult = (fsl_nboot_status_t)g_bootloaderTree_v0->nbootDriver->nboot_sb3_load_block(
679                 ctx->nbootCtx, (uint32_t *)&context->block_buffer[0]);
680         }
681         if (nbootResult == kStatus_NBOOT_Success)
682         {
683             context->block_buffer_position = 0;
684 #if defined(NBOOT_IGNORE_SB3_COMMANDS)
685             if (g_nboot_ctx.processData != NBOOT_IGNORE_SB3_COMMANDS)
686 #endif
687             {
688                 context->in_data_block       = true;
689                 context->data_block          = &context->block_buffer[context->data_block_offset];
690                 context->data_block_position = 0;
691                 context->processedBlocks++;
692                 status = ldr_DoBlock(ctx);
693             }
694 #if defined(NBOOT_IGNORE_SB3_COMMANDS)
695             else
696             {
697                 status = kStatus_Success;
698             }
699 #endif
700         }
701         else
702         {
703             SBLOADER_PRINTF("ROM API: %s, nboot_sb3_load_block is failed, status = %x", __func__, nbootResult);
704             status = kStatus_Fail;
705         }
706     }
707 
708     return status;
709 }
710 
711 ////////////////////////////////////////////////////////////////////////////
712 //! @brief header block handling
713 ////////////////////////////////////////////////////////////////////////////
ldr_DoHeader_v3(fsl_api_core_context_t * ctx)714 static status_t ldr_DoHeader_v3(fsl_api_core_context_t *ctx)
715 {
716     status_t status = kStatus_Success;
717     fsl_nboot_sb3_load_manifest_parms_t manifestParms;
718 
719     fsl_ldr_Context_v3_t *context = get_sbloader_v3_context(ctx);
720 
721     do
722     {
723         fsl_nboot_sb3_header_t *header = (fsl_nboot_sb3_header_t *)(void *)&context->block_buffer[0];
724         if (context->block_buffer_size == sizeof(fsl_nboot_sb3_header_t))
725         {
726             // Update the buffer size to the size of Block 0.
727             context->block_buffer_size = header->imageTotalLength;
728             SBLOADER_PRINTF("ROM API: %s, manifest size = %x, but buffer size =%x", __func__,
729                             context->block_buffer_size, sizeof(context->block_buffer));
730             if (context->block_buffer_size > sizeof(context->block_buffer))
731             {
732                 status = kStatus_Fail;
733                 break;
734             }
735             // Resume the cleared buffer position.
736             context->block_buffer_position = sizeof(fsl_nboot_sb3_header_t);
737 
738             status = kStatus_Success;
739             break;
740         }
741 
742         if (context->block_buffer_size != header->imageTotalLength)
743         {
744             status = kStatus_Fail;
745             break;
746         }
747 
748         (void)memset(&manifestParms, 0, sizeof(fsl_nboot_sb3_load_manifest_parms_t));
749 
750         fsl_nboot_status_t nbootResult = nboot_hal_get_sb3_manifest_params(ctx->nbootCtx, &manifestParms);
751         if (nbootResult != kStatus_NBOOT_Success)
752         {
753             SBLOADER_PRINTF("ROM API: %s, nboot_hal_get_sb3_manifest_params is failed, status = %x", __func__,
754                             nbootResult);
755             status = kStatus_Fail;
756             break;
757         }
758 
759         // call nboot lib to verify the block header
760         if ((get_chip_revision() == 1U) || (get_chip_revision() == 2U))
761         {
762             nbootResult = (fsl_nboot_status_t)g_bootloaderTree_v1->nbootDriver->nboot_sb3_load_manifest(
763                 ctx->nbootCtx, (uint32_t *)(void *)header, &manifestParms);
764         }
765         else
766         {
767             nbootResult = (fsl_nboot_status_t)g_bootloaderTree_v0->nbootDriver->nboot_sb3_load_manifest(
768                 ctx->nbootCtx, (uint32_t *)(void *)header, &manifestParms);
769         }
770         if (nbootResult == kStatus_NBOOT_Success)
771         {
772             context->data_block_offset = (uint8_t)(sizeof(uint32_t) /* blockNumber*/ + header->certificateBlockOffset -
773                                                    sizeof(fsl_nboot_sb3_header_t));
774             context->block_buffer_size = (uint32_t)context->data_block_offset + NBOOT_SB3_CHUNK_SIZE_IN_BYTES;
775             context->block_buffer_position = 0;
776             context->block_size            = header->blockSize;
777             context->block_data_size       = NBOOT_SB3_CHUNK_SIZE_IN_BYTES;
778             context->block_data_total      = context->block_size * ctx->nbootCtx->totalBlocks;
779             context->in_data_section       = false;
780             context->data_section_handled  = 0;
781             context->processedBlocks       = 0;
782             context->Action                = (fsl_pLdrFnc_v3_t)ldr_DoDataRead;
783             status                         = kStatus_Success;
784         }
785         else
786         {
787             SBLOADER_PRINTF("ROM API: %s, nboot_sb3_load_manifest is failed, status = %x", __func__, nbootResult);
788             status = kStatus_Fail;
789         }
790     } while (false);
791 
792     return status;
793 }
794 
795 ////////////////////////////////////////////////////////////////////////////
796 //! @brief Initialize the loader state machine.
797 ////////////////////////////////////////////////////////////////////////////
fsl_sbloader_init(fsl_api_core_context_t * ctx)798 status_t fsl_sbloader_init(fsl_api_core_context_t *ctx)
799 {
800     status_t status = kStatus_InvalidArgument;
801 
802     do
803     {
804         if (ctx == NULL)
805         {
806             break;
807         }
808 
809         fsl_ldr_Context_v3_t *context = ctx->sbloaderCtx;
810 
811         // Initialize the context
812         (void)memset(context, 0, sizeof(fsl_ldr_Context_v3_t));
813         context->block_buffer_size = sizeof(fsl_nboot_sb3_header_t);
814 
815         // Process the first chunk of the image header
816         context->Action = (fsl_pLdrFnc_v3_t)ldr_DoHeader_v3;
817 
818         // Initialize the allowed command set
819         context->commandSet = SBLOADER_V3_CMD_SET_ALL;
820 
821         status = kStatus_Success;
822 
823     } while (false);
824 
825     return status;
826 }
827 
828 ////////////////////////////////////////////////////////////////////////////
829 //! @brief Finalize the loader operations
830 ////////////////////////////////////////////////////////////////////////////
fsl_sbloader_finalize(fsl_api_core_context_t * ctx)831 status_t fsl_sbloader_finalize(fsl_api_core_context_t *ctx)
832 {
833     status_t status = kStatus_Fail;
834 
835     fsl_ldr_Context_v3_t *context = get_sbloader_v3_context(ctx);
836 
837     if (context->data_range_header.cmd == (uint32_t)kSB3_CmdExecute)
838     {
839         status = kStatus_Success;
840     }
841 
842     return status;
843 }
844 
845 ////////////////////////////////////////////////////////////////////////////
846 //! @brief Pump the loader state machine.///////////////////////////////////
fsl_sbloader_pump(fsl_api_core_context_t * ctx,uint8_t * data,uint32_t length)847 static status_t fsl_sbloader_pump(fsl_api_core_context_t *ctx, uint8_t *data, uint32_t length)
848 {
849     status_t status = kStatus_InvalidArgument;
850     do
851     {
852         fsl_ldr_Context_v3_t *context = ctx->sbloaderCtx;
853         uint32_t required             = 0U;
854         uint32_t available            = 0U;
855         uint32_t readPosition         = 0U;
856 
857         while (readPosition < length)
858         {
859             required  = context->block_buffer_size - context->block_buffer_position;
860             available = length - readPosition;
861 
862             // copy what we need to complete a full chunk into the chunk buffer
863             if ((required > 0U) && (available > 0U))
864             {
865                 uint32_t toCopy = required > available ? available : required;
866                 if ((context->block_buffer_position < context->block_buffer_size) &&
867                     (context->block_buffer_position + toCopy <= context->block_buffer_size) &&
868                     (readPosition + toCopy <= length))
869                 {
870                     if ((context->block_buffer_position + toCopy) >= sizeof(context->block_buffer))
871                     {
872                         // block buffer over-flow.
873                         SBLOADER_PRINTF("ROM API: %s, block buffer is overflown", __func__);
874                         status = kStatus_Fail;
875                         break;
876                     }
877                     (void)memcpy(&context->block_buffer[context->block_buffer_position], &data[readPosition], toCopy);
878                     required -= toCopy;
879                     available -= toCopy;
880                     readPosition += toCopy;
881                     context->block_buffer_position += toCopy;
882                     status = kStatus_Success;
883                 }
884                 else
885                 {
886                     status = kStatus_Fail;
887                     break;
888                 }
889             }
890 
891             if (required == 0U)
892             {
893                 // a full chunk was filled to process it
894                 context->block_buffer_position = 0U;
895                 status                         = (context->Action)(ctx);
896 
897                 if (status != kStatus_Success)
898                 {
899                     if (status != (status_t)kStatusRomLdrPendingJumpCommand)
900                     {
901                         SBLOADER_PRINTF("sbloader Action failed: 0x%08x", status);
902                     }
903                     break;
904                 }
905             }
906             else if (available == 0U)
907             {
908                 // otherwise we are just going to wait for more data
909                 status = (status_t)kStatusRomLdrDataUnderrun;
910                 break;
911             }
912             else
913             {
914                 ; /* None to do */
915             }
916         }
917     } while (false);
918 
919     return status;
920 }
921 
922 ////////////////////////////////////////////////////////////////////////////
923 //! @brief Read flash area loading to RAM buffer.
924 // Direct read from flash is not allowed when remapping is active.
925 // buf             : pointer to RAM buffer, its size must be sufficient to receive
926 //                   the required number of bytes.
927 // src_flash_offset: 'virtual' address in flash relative to start of flash storage.
928 //                   Actual 'physical' address results from the addition of the remap offset.
929 // read_sz         : Number of bytes to be read.
930 ////////////////////////////////////////////////////////////////////////////
ldr_ReadFromFlash(uint8_t * buf,uint32_t src_flash_offset,size_t read_sz)931 static status_t ldr_ReadFromFlash(uint8_t * buf, uint32_t src_flash_offset, size_t read_sz)
932 {
933     status_t st;
934     static const uint32_t mflash_base = (1u << 27);
935     uint32_t remap_offset = _ActiveApplicationRemapOffset();
936     if (remap_offset == 0U)
937     {
938         memcpy(buf, (void*)src_flash_offset, read_sz);
939         st = kStatus_Success;
940     }
941     else
942     {
943         // similar to mflash_drv_log2phys
944         uint32_t phys_offset = (src_flash_offset + remap_offset) & ~mflash_base;
945         st = mflash_drv_read(phys_offset, (uint32_t *)buf, read_sz);
946     }
947     return st;
948 }
949 
950 ////////////////////////////////////////////////////////////////////////////
951 //! @brief Read SB3 area descriptor.
952 // Direct read from flash is not allowed when remapping is active.
953 // hdr       : pointer to RAM fsl_nboot_sb3_header_t structure.
954 // sourceAddr: 'virtual' address where SB3 header is expected.
955 ////////////////////////////////////////////////////////////////////////////
read_nboot_sb3_header(fsl_nboot_sb3_header_t * hdr,uint32_t sourceAddr)956 status_t read_nboot_sb3_header(fsl_nboot_sb3_header_t * hdr, uint32_t sourceAddr)
957 {
958    return ldr_ReadFromFlash((uint8_t*)hdr, sourceAddr, sizeof(fsl_nboot_sb3_header_t));
959 }
960 
961 ////////////////////////////////////////////////////////////////////////////
962 //! @brief load service with format of sb3
963 // readOffset: image offset in flash
964 ////////////////////////////////////////////////////////////////////////////
loader_process_sb_file(uint32_t readOffset)965 status_t loader_process_sb_file(uint32_t readOffset)
966 {
967     status_t status                    = kStatus_Fail;
968     uint32_t packetLength              = sizeof(packetBuf);
969     s_fsl_api_core_context.sbloaderCtx = &s_sbloader_context;
970     s_fsl_api_core_context.nbootCtx    = &g_nbootCtx;
971     bool elsFlag                       = false;
972     uint32_t CSS_CTRL_context          = 0;
973 #ifdef CONFIG_FW_VDLLV2
974     uint32_t counter;
975 #endif
976 
977     do
978     {
979         (void)POWER_EnableGDetVSensors();
980         if (((CLKCTL0->PSCCTL0 & CLKCTL0_PSCCTL0_ELS_MASK) == 0U) ||
981             ((CLKCTL0->PSCCTL1 & CLKCTL0_PSCCTL1_ELS_APB_MASK) == 0U) ||
982             ((RSTCTL0->PRSTCTL0 & RSTCTL0_PRSTCTL0_ELS_MASK) != 0U))
983         {
984             elsFlag = true;
985             CLOCK_EnableClock(kCLOCK_Els);
986             CLOCK_EnableClock(kCLOCK_ElsApb);
987             RESET_PeripheralReset(kELS_RST_SHIFT_RSTn);
988         }
989 
990 #if defined(MBEDTLS_THREADING_C) && defined(MBEDTLS_THREADING_ALT)
991         (void)mcux_els_mutex_lock();
992 #endif
993 
994         if ((get_chip_revision() == 1U) || (get_chip_revision() == 2U))
995         {
996             status = (int32_t)g_bootloaderTree_v1->nbootDriver->nboot_context_init(s_fsl_api_core_context.nbootCtx);
997         }
998         else
999         {
1000             status = (int32_t)g_bootloaderTree_v0->nbootDriver->nboot_context_init(s_fsl_api_core_context.nbootCtx);
1001         }
1002         if (status != (status_t)kStatus_NBOOT_Success)
1003         {
1004             break;
1005         }
1006 
1007         status = fsl_sbloader_init(&s_fsl_api_core_context);
1008         if (status != kStatus_Success)
1009         {
1010             break;
1011         }
1012 
1013         // Pump the sbloader content and do sbloader handling until ROM see the jump command and jump to the image
1014         while (true)
1015         {
1016             memcpy(packetBuf, (void*)readOffset, packetLength);
1017 
1018             if ((get_chip_revision() == 1U) || (get_chip_revision() == 2U))
1019             {
1020                 status = fsl_sbloader_pump(&s_fsl_api_core_context, packetBuf, packetLength);
1021             }
1022             else
1023             {
1024                 status = g_bootloaderTree_v0->iapApiDriver->fsl_sbloader_pump(&s_fsl_api_core_context, packetBuf,
1025                                                                               packetLength);
1026             }
1027 
1028             // kStatusRomLdrDataUnderrun means need more data
1029             // kStatusRomLdrSectionOverrun means we reached the end of the sb file processing
1030             // either of these are OK
1031             if ((status == (status_t)kStatusRomLdrDataUnderrun) || (status == (status_t)kStatusRomLdrSectionOverrun))
1032             {
1033                 status = kStatus_Success;
1034             }
1035             else if (status == (status_t)kStatusRomLdrPendingJumpCommand)
1036             {
1037                 status = fsl_sbloader_finalize(&s_fsl_api_core_context);
1038 #ifdef CONFIG_FW_VDLLV2
1039                 assert((readOffset & 0x3U) == 0U);
1040                 for (counter = 0; counter < (packetLength + 7U) >> 2U; counter++)
1041                 {
1042                     if (*(uint32_t *)readOffset == TAG_SB_V3)
1043                     {
1044                         vdll_image_base = readOffset;
1045                         break;
1046                     }
1047                     else
1048                     {
1049                         readOffset += 4U;
1050                     }
1051                 }
1052 #endif
1053                 break;
1054             }
1055             else
1056             {
1057                 ; /* No necessary actions. */
1058             }
1059 
1060             if (status != kStatus_Success)
1061             {
1062                 break;
1063             }
1064 
1065             readOffset += packetLength;
1066         }
1067     } while (false);
1068 
1069     if (get_chip_revision() == 0U)
1070     {
1071         CSS_CTRL_context = ELS->ELS_CTRL;
1072     }
1073 
1074     if ((get_chip_revision() == 1U) || (get_chip_revision() == 2U))
1075     {
1076         (void)g_bootloaderTree_v1->nbootDriver->nboot_context_deinit(s_fsl_api_core_context.nbootCtx);
1077     }
1078     else
1079     {
1080         (void)g_bootloaderTree_v0->nbootDriver->nboot_context_deinit(s_fsl_api_core_context.nbootCtx);
1081     }
1082 
1083     if (get_chip_revision() == 0U)
1084     {
1085         ELS->ELS_CTRL = (CSS_CTRL_context & 0xFFU);
1086     }
1087 
1088 #if defined(MBEDTLS_THREADING_C) && defined(MBEDTLS_THREADING_ALT)
1089     (void)mcux_els_mutex_unlock();
1090 #endif
1091 
1092     if (elsFlag == true)
1093     {
1094         RESET_SetPeripheralReset(kELS_RST_SHIFT_RSTn);
1095         CLOCK_DisableClock(kCLOCK_ElsApb);
1096         CLOCK_DisableClock(kCLOCK_Els);
1097     }
1098     POWER_DisableGDetVSensors();
1099 
1100     return status;
1101 }
1102 
1103 ////////////////////////////////////////////////////////////////////////////
1104 //! @brief load service with format of raw binary image
1105 // readOffset: image offset in flash
1106 ////////////////////////////////////////////////////////////////////////////
loader_process_raw_file(uint32_t readOffset)1107 static status_t loader_process_raw_file(uint32_t readOffset)
1108 {
1109     status_t status = kStatus_Fail;
1110     uint32_t *src_addr;
1111     uint32_t *dst_addr;
1112     uint32_t code_size;
1113     uint32_t *data_ptr      = (uint32_t *)readOffset;
1114     uint32_t total_raw_size = 0;
1115 
1116 #ifdef CONFIG_FW_VDLLV2
1117     if ((*data_ptr == LOADER_RAW_BINARY_FORMAT) && (*(data_ptr + 1) == LOADER_VDLL_RAW_BINARY_FORMAT))
1118     {
1119         src_addr  = data_ptr + 4;
1120         dst_addr  = (uint32_t *)*(data_ptr + 2);
1121         code_size = *(data_ptr + 3);
1122         (void)memcpy(dst_addr, src_addr, code_size);
1123         status = kStatus_Success;
1124     }
1125     else
1126 #endif
1127     {
1128         do
1129         {
1130             if (*data_ptr != LOADER_RAW_BINARY_FORMAT)
1131             {
1132                 break;
1133             }
1134 
1135             src_addr  = data_ptr + 4;
1136             dst_addr  = (uint32_t *)*(data_ptr + 2);
1137             code_size = *(data_ptr + 3);
1138             // Check for raw ending segment
1139             if (((uint32_t)src_addr == 0xffffffffU) || ((uint32_t)dst_addr == 0xffffffffU))
1140             {
1141                 if (code_size == total_raw_size)
1142                 {
1143                     status = kStatus_Success;
1144 #ifdef CONFIG_FW_VDLLV2
1145                     vdll_image_base = (uint32_t)(data_ptr + 4);
1146 #endif
1147                 }
1148                 break;
1149             }
1150 
1151             (void)memcpy(dst_addr, src_addr, code_size);
1152             data_ptr += 4U + (code_size >> 2U);
1153             total_raw_size += code_size;
1154         } while (true);
1155     }
1156 
1157     return status;
1158 }
1159 
loader_process_raw_file_monolithic(uint32_t readOffset)1160 static status_t loader_process_raw_file_monolithic(uint32_t readOffset)
1161 {
1162     status_t status = kStatus_Fail;
1163     uint32_t *dst_addr;
1164     uint32_t code_size;
1165     uint32_t sz;
1166 
1167 
1168     uint32_t total_raw_size = 0U;
1169     uint8_t staging_buf[STAGING_BUF_SZ] = { 0u };
1170 
1171     do {
1172         sb3_load_desc_t *p_desc = (sb3_load_desc_t*)&staging_buf[0];
1173         status_t flash_st;
1174         /* Firs read the SB3 area descriptor */
1175         flash_st = ldr_ReadFromFlash(&staging_buf[0], readOffset, sizeof(sb3_load_desc_t));
1176         if (flash_st != kStatus_Success)
1177         {
1178             break;
1179         }
1180         readOffset += sizeof(sb3_load_desc_t);
1181 
1182         if (p_desc->fmt != LOADER_RAW_BINARY_FORMAT)
1183         {
1184             break;
1185         }
1186 
1187         dst_addr  = (uint32_t*)p_desc->dst_addr;
1188         code_size = p_desc->area_sz;
1189 
1190         // Check for raw ending segment
1191         if (p_desc->dst_addr == 0xffffffffU)
1192         {
1193             if (code_size == total_raw_size)
1194             {
1195                 status = kStatus_Success;
1196 #ifdef CONFIG_FW_VDLLV2
1197                 vdll_image_base = readOffset;
1198 #endif
1199             }
1200             break;
1201         }
1202 
1203         /* start of indirect memcpy to destination */
1204         sz = code_size;
1205         while (sz >= STAGING_BUF_SZ)
1206         {
1207             flash_st = ldr_ReadFromFlash(&staging_buf[0], readOffset, STAGING_BUF_SZ);
1208             if (flash_st != kStatus_Success)
1209             {
1210                 break;
1211             }
1212             (void)memcpy(dst_addr, &staging_buf[0], STAGING_BUF_SZ);
1213             readOffset += STAGING_BUF_SZ;
1214             dst_addr += STAGING_BUF_SZ/4;
1215             sz -= STAGING_BUF_SZ;
1216         }
1217         if (flash_st != kStatus_Success)
1218         {
1219             break;
1220         }
1221         /* last chunk smaller than staging buffer */
1222         if (sz > 0U)
1223         {
1224             flash_st = ldr_ReadFromFlash(&staging_buf[0], readOffset, sz);
1225             if (flash_st != kStatus_Success)
1226             {
1227                 break;
1228             }
1229             (void)memcpy(dst_addr, &staging_buf[0], sz);
1230             readOffset += sz;
1231             dst_addr += (sz+3U)/4U;
1232         }
1233         /* at this point are is fully consumed and copied to destination : */
1234 #ifdef CONFIG_FW_VDLLV2
1235         if ((p_desc->sub_fmt == LOADER_VDLL_RAW_BINARY_FORMAT))
1236         {
1237             status = kStatus_Success;
1238             break;
1239         }
1240 #endif
1241         total_raw_size += code_size;
1242 
1243     } while (true);
1244 
1245     return status;
1246 }
1247 
1248 #ifndef __ZEPHYR__
__FlexSpiFlashInit(void)1249 static bool __FlexSpiFlashInit(void)
1250 {
1251     bool ret = false;
1252     if (((CLKCTL0->PSCCTL0 & CLKCTL0_PSCCTL0_FLEXSPI0_MASK) == 0U) ||
1253         ((RSTCTL0->PRSTCTL0 & RSTCTL0_PRSTCTL0_FLEXSPI0_MASK) != 0U))
1254     {
1255         CLOCK_EnableClock(kCLOCK_Flexspi);
1256         RESET_PeripheralReset(kFLEXSPI_RST_SHIFT_RSTn);
1257         BOARD_SetFlexspiClock(FLEXSPI, 2U, 2U);
1258         BOARD_InitFlash(FLEXSPI);
1259         ret = true;
1260     }
1261     return ret;
1262 }
1263 
__FlexSpiFlashDeInit(void)1264 static void __FlexSpiFlashDeInit(void)
1265 {
1266     RESET_ClearPeripheralReset(kFLEXSPI_RST_SHIFT_RSTn);
1267     BOARD_DeinitFlash(FLEXSPI);
1268     CLOCK_AttachClk(kNONE_to_FLEXSPI_CLK);
1269     CLOCK_DisableClock(kCLOCK_Flexspi);
1270     RESET_SetPeripheralReset(kFLEXSPI_RST_SHIFT_RSTn);
1271 }
1272 
1273 #endif
1274 
__OtpInit(void)1275 static int __OtpInit(void)
1276 {
1277     int ret = 0; /* will stay 0 if nothing to do */
1278     if (((CLKCTL0->PSCCTL1 & CLKCTL0_PSCCTL1_OTP_MASK) == 0U) ||
1279         ((RSTCTL0->PRSTCTL1 & RSTCTL0_PRSTCTL1_OTP_MASK) != 0U))
1280     {
1281         status_t st;
1282 #ifdef USE_OCOTP_DRIVER_IN_LOAD_SERVICE
1283         st = OCOTP_OtpInit();
1284 #else
1285         if ((get_chip_revision() == 1U) || (get_chip_revision() == 2U))
1286         {
1287             st = g_bootloaderTree_v1->otpDriver->init(0U);
1288         }
1289         else
1290         {
1291             RESET_PeripheralReset(kOTP_RST_SHIFT_RSTn);
1292             st = g_bootloaderTree_v0->otpDriver->init(0U);
1293         }
1294 #endif
1295         if (st != kStatus_Success)
1296         {
1297             ret = -1;
1298         }
1299         else
1300         {
1301             ret = 1;
1302         }
1303     }
1304     return ret;
1305 }
1306 
__OtpDeInit(void)1307 static int __OtpDeInit(void)
1308 {
1309     int ret = -1;
1310 #ifdef USE_OCOTP_DRIVER_IN_LOAD_SERVICE
1311         if (OCOTP_OtpDeinit() == kStatus_Success)
1312         {
1313             ret = 0;
1314         }
1315 #else
1316         if ((get_chip_revision() == 1U) || (get_chip_revision() == 2U))
1317         {
1318             if (g_bootloaderTree_v1->otpDriver->deinit() == kStatus_Success)
1319             {
1320                 ret = 0;
1321             }
1322         }
1323         else
1324         {
1325             if (g_bootloaderTree_v0->otpDriver->deinit() == kStatus_Success)
1326             {
1327                 ret = 0;
1328             }
1329         }
1330 #endif
1331     return ret;
1332 }
1333 
1334 
1335 ////////////////////////////////////////////////////////////////////////////
1336 //! @brief load service
1337 // loadTarget: LOAD_WIFI_FIRMWARE / LOAD_BLE_FIRMWARE / LOAD_15D4_FIRMWARE
1338 // sourceAddr: load firmware source address, if 0 load default address
1339 ////////////////////////////////////////////////////////////////////////////
load_service(LOAD_Target_Type loadTarget,uint32_t sourceAddr)1340 status_t load_service(LOAD_Target_Type loadTarget, uint32_t sourceAddr)
1341 {
1342     status_t status = kStatus_Fail;
1343     fsl_nboot_sb3_header_t *pt_a_ptr;
1344     fsl_nboot_sb3_header_t *pt_b_ptr;
1345     fsl_nboot_sb3_header_t *active_pt_ptr;
1346     uint32_t firmwareVersion = 0xFFFFFFFFU;
1347     int otp_status           = 0;
1348 #ifndef __ZEPHYR__
1349     bool flexspiFlag         = __FlexSpiFlashInit();
1350 #endif
1351 
1352     if (LOAD_WIFI_FIRMWARE == loadTarget)
1353     {
1354         if (sourceAddr == 0U)
1355         {
1356             pt_a_ptr = (fsl_nboot_sb3_header_t *)WIFI_IMAGE_A_OFFSET;
1357             pt_b_ptr = (fsl_nboot_sb3_header_t *)WIFI_IMAGE_B_OFFSET;
1358         }
1359         else
1360         {
1361             pt_a_ptr = (fsl_nboot_sb3_header_t *)sourceAddr;
1362             pt_b_ptr = (fsl_nboot_sb3_header_t *)(sourceAddr + WIFI_IMAGE_SIZE_MAX);
1363         }
1364     }
1365     else if (LOAD_BLE_FIRMWARE == loadTarget)
1366     {
1367         if (sourceAddr == 0U)
1368         {
1369             pt_a_ptr = (fsl_nboot_sb3_header_t *)BLE_IMAGE_A_OFFSET;
1370             pt_b_ptr = (fsl_nboot_sb3_header_t *)BLE_IMAGE_B_OFFSET;
1371         }
1372         else
1373         {
1374             pt_a_ptr = (fsl_nboot_sb3_header_t *)sourceAddr;
1375             pt_b_ptr = (fsl_nboot_sb3_header_t *)(sourceAddr + BLE_IMAGE_SIZE_MAX);
1376         }
1377     }
1378     else if (LOAD_15D4_FIRMWARE == loadTarget)
1379     {
1380         if (sourceAddr == 0U)
1381         {
1382             pt_a_ptr = (fsl_nboot_sb3_header_t *)Z154_IMAGE_A_OFFSET;
1383             pt_b_ptr = (fsl_nboot_sb3_header_t *)Z154_IMAGE_B_OFFSET;
1384         }
1385         else
1386         {
1387             pt_a_ptr = (fsl_nboot_sb3_header_t *)sourceAddr;
1388             pt_b_ptr = (fsl_nboot_sb3_header_t *)(sourceAddr + Z154_IMAGE_SIZE_MAX);
1389         }
1390     }
1391 #ifdef CONFIG_FW_VDLLV2
1392     else if (LOAD_WIFI_VDLL_FIRMWARE == loadTarget)
1393     {
1394         assert(vdll_image_base != 0U);
1395         pt_a_ptr = (fsl_nboot_sb3_header_t *)(vdll_image_base + sourceAddr);
1396         pt_b_ptr = NULL;
1397     }
1398 #endif
1399     else
1400     {
1401         return kStatus_Fail;
1402     }
1403 
1404 #ifdef MCUBOOT_APPLICATION
1405     {
1406         /* Skip MCUBoot header if present */
1407 
1408         struct image_header *header;
1409 
1410         header = (void *)pt_a_ptr;
1411         if (header->ih_magic == IMAGE_MAGIC)
1412         {
1413             pt_a_ptr = (void *)(((uint8_t *)pt_a_ptr) + header->ih_hdr_size);
1414         }
1415 
1416         header = (void *)pt_b_ptr;
1417         if (header->ih_magic == IMAGE_MAGIC)
1418         {
1419             pt_b_ptr = (void *)(((uint8_t *)pt_b_ptr) + header->ih_hdr_size);
1420         }
1421     }
1422 #endif
1423 
1424     otp_status = __OtpInit();
1425     if (otp_status < 0)
1426     {
1427         return kStatus_Fail;
1428     }
1429 
1430 #ifdef CONFIG_FW_VDLLV2
1431     if (LOAD_WIFI_VDLL_FIRMWARE != loadTarget)
1432 #endif
1433     {
1434         if (nboot_hal_get_secure_firmware_version(&firmwareVersion, loadTarget) != kStatus_NBOOT_Success)
1435         {
1436             return kStatus_Fail;
1437         }
1438 
1439         // imu init may be called before or after load_service(), not sure user will do in which sequence.
1440         // If imu init is before load_service(), it is not appropriate do Power-Off here, then comment out Power-Off.
1441         // power_off_device_impl(); // temporarily comment out for PDM Non-UPF version
1442 
1443         power_on_device_impl(loadTarget);
1444     }
1445 
1446     /* Check partition TAG and select active partition */
1447     if ((pt_a_ptr->magic != TAG_SB_V3) && (pt_b_ptr->magic != TAG_SB_V3))
1448     {
1449         active_pt_ptr = pt_a_ptr;
1450         status        = loader_process_raw_file((uint32_t)active_pt_ptr);
1451     }
1452     else if ((pt_a_ptr->magic == TAG_SB_V3) && (pt_b_ptr->magic != TAG_SB_V3))
1453     {
1454         active_pt_ptr = pt_a_ptr;
1455 #ifdef CONFIG_FW_VDLLV2
1456         if (LOAD_WIFI_VDLL_FIRMWARE != loadTarget)
1457         {
1458 #endif
1459             if (active_pt_ptr->firmwareVersion < firmwareVersion)
1460             {
1461                 return kStatus_Fail;
1462             }
1463 #ifdef CONFIG_FW_VDLLV2
1464         }
1465 #endif
1466         status = loader_process_sb_file((uint32_t)active_pt_ptr);
1467     }
1468     else if ((pt_a_ptr->magic != TAG_SB_V3) && (pt_b_ptr->magic == TAG_SB_V3))
1469     {
1470         active_pt_ptr = pt_b_ptr;
1471         if (active_pt_ptr->firmwareVersion < firmwareVersion)
1472         {
1473             return kStatus_Fail;
1474         }
1475         status = loader_process_sb_file((uint32_t)active_pt_ptr);
1476     }
1477     else
1478     {
1479         if (pt_a_ptr->firmwareVersion >= pt_b_ptr->firmwareVersion)
1480         {
1481             active_pt_ptr = pt_a_ptr;
1482         }
1483         else
1484         {
1485             active_pt_ptr = pt_b_ptr;
1486         }
1487 
1488         if (active_pt_ptr->firmwareVersion < firmwareVersion)
1489         {
1490             return kStatus_Fail;
1491         }
1492         status = loader_process_sb_file((uint32_t)active_pt_ptr);
1493     }
1494 
1495     if (otp_status != 0)
1496     {
1497         /* OTP init was done here */
1498         (void)__OtpDeInit();
1499     }
1500 
1501     if (status == kStatus_Success)
1502     {
1503         reset_device(loadTarget);
1504     }
1505 
1506 #ifndef __ZEPHYR__
1507     if (flexspiFlag)
1508     {
1509         __FlexSpiFlashDeInit();
1510     }
1511 #endif
1512     return status;
1513 }
1514 
1515 
load_service_monolithic(LOAD_Target_Type loadTarget,uint32_t sourceAddr)1516 static status_t load_service_monolithic(LOAD_Target_Type loadTarget, uint32_t sourceAddr)
1517 {
1518     status_t status = kStatus_Fail;
1519     uint32_t hdr_a = 0UL;
1520     fsl_nboot_sb3_header_t boot_hdr;
1521     fsl_nboot_sb3_header_t *pt_a_ptr = &boot_hdr;
1522     uint32_t firmwareVersion = 0xFFFFFFFFU;
1523     uint32_t sel_fw_ver;
1524     int otp_status           = 0;
1525 
1526     memset(&boot_hdr, 0xff, sizeof(fsl_nboot_sb3_header_t));
1527 
1528 #ifndef __ZEPHYR__
1529     bool flexspiFlag         = __FlexSpiFlashInit();
1530 #endif
1531     (void)mflash_drv_init();
1532     do {
1533         status_t ret = kStatus_Fail;
1534         if ((LOAD_WIFI_FW_MONOLITHIC != loadTarget) && (LOAD_BLE_FW_MONOLITHIC != loadTarget) && (LOAD_15D4_FW_MONOLITHIC != loadTarget))
1535         {
1536             break;
1537         }
1538         if (sourceAddr == 0UL)
1539         {
1540             break;
1541         }
1542         hdr_a = sourceAddr;
1543 
1544         otp_status = __OtpInit();
1545         if (otp_status < 0)
1546         {
1547             break;
1548         }
1549 
1550         if (nboot_hal_get_secure_firmware_version(&firmwareVersion, loadTarget) != kStatus_NBOOT_Success)
1551         {
1552            break;
1553         }
1554 
1555         // imu init may be called before or after load_service(), not sure user will do in which sequence.
1556         // If imu init is before load_service(), it is not appropriate do Power-Off here, then comment out Power-Off.
1557         // power_off_device_impl(); // temporarily comment out for PDM Non-UPF version
1558 
1559         power_on_device_impl(loadTarget);
1560 
1561         ret = ldr_ReadFromFlash((uint8_t*)pt_a_ptr, hdr_a, sizeof(fsl_nboot_sb3_header_t ));
1562         if (ret != kStatus_Success)
1563         {
1564             break;
1565         }
1566         /* Check partition TAG and select active partition */
1567         if (pt_a_ptr->magic == TAG_SB_V3)
1568         {
1569             sel_fw_ver = pt_a_ptr->firmwareVersion;
1570 
1571             if (sel_fw_ver < firmwareVersion)
1572             {
1573                 break;
1574             }
1575             status = loader_process_sb_file(hdr_a);
1576         }
1577         else
1578         {
1579             status = loader_process_raw_file_monolithic(hdr_a);
1580         }
1581 
1582     } while (false);
1583 
1584     if (otp_status != 0)
1585     {
1586         /* OTP init was done here so undo it here */
1587         (void)__OtpDeInit();
1588     }
1589 
1590     if (status == kStatus_Success)
1591     {
1592         reset_device(loadTarget);
1593     }
1594 #ifndef __ZEPHYR__
1595     if (flexspiFlag)
1596     {
1597         __FlexSpiFlashDeInit();
1598     }
1599 #endif
1600     return status;
1601 }
1602 
1603 ////////////////////////////////////////////////////////////////////////////
1604 //! @brief get chip revision
1605 ////////////////////////////////////////////////////////////////////////////
get_chip_revision(void)1606 uint8_t get_chip_revision(void)
1607 {
1608     return (uint8_t)(SOCCTRL->CHIP_INFO & SOCCTRL_CHIP_INFO_REV_NUM_MASK);
1609 }
1610 
1611 //! @}
1612 ////////////////////////////////////////////////////////////////////////////
1613 // EOF
1614 ////////////////////////////////////////////////////////////////////////////