diff --git a/connectivity/drivers/emac/TARGET_Cypress/COMPONENT_WHD/interface/whd_emac.cpp b/connectivity/drivers/emac/TARGET_Cypress/COMPONENT_WHD/interface/whd_emac.cpp index 63b67bdea3..111839ec6c 100644 --- a/connectivity/drivers/emac/TARGET_Cypress/COMPONENT_WHD/interface/whd_emac.cpp +++ b/connectivity/drivers/emac/TARGET_Cypress/COMPONENT_WHD/interface/whd_emac.cpp @@ -27,10 +27,15 @@ #include "events/mbed_shared_queues.h" #include "whd_wlioctl.h" #include "whd_buffer_api.h" +#include "wiced_resource.h" #include "cybsp_wifi.h" #include "emac_eapol.h" #include "cy_result.h" +#if defined(CY_EXT_WIFI_FW_STORAGE) && !MBED_CONF_TARGET_XIP_ENABLE +#include "cy_ext_wifi_fw_reserved_region_bd.h" +#endif /* defined(CY_EXT_WIFI_FW_STORAGE) && !MBED_CONF_TARGET_XIP_ENABLE */ + #define NULL_MAC(a) ( ( ( ( (unsigned char *)a )[0] ) == 0 ) && \ ( ( ( (unsigned char *)a )[1] ) == 0 ) && \ ( ( ( (unsigned char *)a )[2] ) == 0 ) && \ @@ -112,7 +117,17 @@ bool WHD_EMAC::power_up() WHD_EMAC &emac_other = WHD_EMAC::get_instance(interface_type == WHD_STA_ROLE ? WHD_AP_ROLE : WHD_STA_ROLE); if (!emac_other.powered_up) { +#if defined(CY_EXT_WIFI_FW_STORAGE) && !MBED_CONF_TARGET_XIP_ENABLE + CyReservedRegionBlockDevice *reserved_region_bd = cy_get_ext_wifi_fw_reserved_region_bd(); + reserved_region_bd->init(); + + extern whd_resource_source_t cy_ext_wifi_fw_resource_ops; + res = cybsp_wifi_init_primary_extended(&ifp /* OUT */, &cy_ext_wifi_fw_resource_ops, NULL, NULL); + + reserved_region_bd->deinit(); +#else res = cybsp_wifi_init_primary(&ifp /* OUT */); +#endif /* defined(CY_EXT_WIFI_FW_STORAGE) && !MBED_CONF_TARGET_XIP_ENABLE */ } else { ifp = emac_other.ifp; } @@ -295,4 +310,13 @@ extern "C" } } +#if defined(CY_EXT_WIFI_FW_STORAGE) && !MBED_CONF_TARGET_XIP_ENABLE + resource_result_t platform_read_external_resource(const resource_hnd_t *resource, uint32_t offset, uint32_t maxsize, uint32_t *size, void *buffer) + { + CyReservedRegionBlockDevice *bd = cy_get_ext_wifi_fw_reserved_region_bd(); + int status = bd->reserved_read(buffer, (mbed::bd_addr_t) resource->val.external_storage_context + offset, *size); + return (status == 0) ? RESOURCE_SUCCESS : RESOURCE_FILE_READ_FAIL; + } +#endif /* defined(CY_EXT_WIFI_FW_STORAGE) && !MBED_CONF_TARGET_XIP_ENABLE */ + } // extern "C" diff --git a/targets/TARGET_Cypress/TARGET_PSOC6/common/ext-wifi-fw/cy_ext_wifi_fw_reserved_region_bd.cpp b/targets/TARGET_Cypress/TARGET_PSOC6/common/ext-wifi-fw/cy_ext_wifi_fw_reserved_region_bd.cpp new file mode 100644 index 0000000000..8db6460d5e --- /dev/null +++ b/targets/TARGET_Cypress/TARGET_PSOC6/common/ext-wifi-fw/cy_ext_wifi_fw_reserved_region_bd.cpp @@ -0,0 +1,89 @@ +/***************************************************************************//** +* \file cy_ext_wifi_fw_reserved_region_bd.cpp +* +* \brief +* Block device use to interact with external memory without interfering with +* the region reserved for the WiFi firmware. +* +* Creates a canonical instance that can be accessed via cy_get_ext_wifi_fw_reserved_region_bd(). +* Provides overrides for Mbed OS functions so that storage mechanisms such as KVStore +* will default to using this block device. +* +******************************************************************************** +* \copyright +* Copyright 2020 Cypress Semiconductor Corporation +* SPDX-License-Identifier: Apache-2.0 +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +// Use of xip-enable by user overrides definition of CY_EXT_WIFI_FW_STORAGE in target configuration +#if defined(CY_EXT_WIFI_FW_STORAGE) && !MBED_CONF_TARGET_XIP_ENABLE + +#include "cy_ext_wifi_fw_reserved_region_bd.h" +#include "cy_wifi_fw_section.h" +#include "QSPIFBlockDevice.h" + +BlockDevice *cy_get_ext_wifi_fw_reserved_region_underlying_bd() +{ +#if CY_EXT_WIFI_FW_STORAGE == QSPIF + static QSPIFBlockDevice underlying_bd; +#else +#error "Invalid WiFi storage type" +#endif + + return &underlying_bd; +} + +CyReservedRegionBlockDevice *cy_get_ext_wifi_fw_reserved_region_bd() +{ + BlockDevice *underlying_bd = cy_get_ext_wifi_fw_reserved_region_underlying_bd(); + static CyReservedRegionBlockDevice default_instance(underlying_bd, (mbed::bd_addr_t) CY_WIFI_FW_SECTION_END - (mbed::bd_addr_t) CY_WIFI_FW_SECTION_START); + return &default_instance; +} + +extern "C" { +extern void cy_ext_wifi_fw_resources_update_handles(void *image_addr, unsigned long image_size, void *clm_blob_addr, unsigned long clm_blob_size); +} + +int cy_update_ext_wifi_fw_location_and_size(mbed::bd_addr_t image_addr, mbed::bd_size_t image_size, mbed::bd_addr_t clm_blob_addr, mbed::bd_size_t clm_blob_size) +{ + CyReservedRegionBlockDevice *bd = cy_get_ext_wifi_fw_reserved_region_bd(); + // If the reserved region end is NULL, the block device hasn't been initialized yet, so we can't perform this check + if ((bd->reserved_region_end() != 0) && (image_addr + image_size > bd->reserved_region_end() || clm_blob_addr + clm_blob_size > bd->reserved_region_end())) + { + // Should not exceed originally computed reserved region size, as this will break anything that was using the rest of external storage + return -1; + } + + // These addresses are not valid pointers, but are converted to pointers so as to be used with the WHD resource handles + cy_ext_wifi_fw_resources_update_handles((void *) image_addr, image_size, (void *) clm_blob_addr, clm_blob_size); + + return 0; +} + +// +// Overrides for other Mbed OS storage mechanisms to that this is the default block device +// + +BlockDevice *get_other_blockdevice() +{ + return cy_get_ext_wifi_fw_reserved_region_bd(); +} + +BlockDevice *BlockDevice::get_default_instance() +{ + return cy_get_ext_wifi_fw_reserved_region_bd(); +} + +#endif /* defined(CY_EXT_WIFI_FW_STORAGE) && !MBED_CONF_TARGET_XIP_ENABLE */ diff --git a/targets/TARGET_Cypress/TARGET_PSOC6/common/ext-wifi-fw/cy_ext_wifi_fw_reserved_region_bd.h b/targets/TARGET_Cypress/TARGET_PSOC6/common/ext-wifi-fw/cy_ext_wifi_fw_reserved_region_bd.h new file mode 100644 index 0000000000..50946f5106 --- /dev/null +++ b/targets/TARGET_Cypress/TARGET_PSOC6/common/ext-wifi-fw/cy_ext_wifi_fw_reserved_region_bd.h @@ -0,0 +1,90 @@ +/***************************************************************************//** +* \file cy_ext_wifi_fw_reserved_region_bd.h +* +* \brief +* Block device use to interact with external memory without interfering with +* the region reserved for the WiFi firmware. +* +* Creates a canonical instance that can be accessed via cy_get_ext_wifi_fw_reserved_region_bd(). +* Provides overrides for Mbed OS functions so that storage mechanisms such as KVStore +* will default to using this block device. +* +* See cy_get_ext_wifi_fw_reserved_region_bd() for more details. +* +******************************************************************************** +* \copyright +* Copyright 2020 Cypress Semiconductor Corporation +* SPDX-License-Identifier: Apache-2.0 +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#ifndef CY_EXT_WIFI_FW_RESERVED_REGION_BD_H +#define CY_EXT_WIFI_FW_RESERVED_REGION_BD_H + +// Use of xip-enable by user overrides definition of CY_EXT_WIFI_FW_STORAGE in target configuration +#if defined(CY_EXT_WIFI_FW_STORAGE) && !MBED_CONF_TARGET_XIP_ENABLE + +#include "CyReservedRegionBlockDevice.h" + +/** + * Get the canonical instance of the underlying block device used by the canonical + * CyReservedRegionBlockDevice instance (retrieved via cy_get_ext_wifi_fw_reserved_region_bd()). + * Uses the macro CY_EXT_WIFI_FW_STORAGE to determine the type of the underlying block device. + * Valid values of CY_EXT_WIFI_FW_STORAGE are: QSPIF. + * + * @return A pointer to the canonical instance of the underlying block device + */ +BlockDevice *cy_get_ext_wifi_fw_reserved_region_underlying_bd(); + +/** + * Get the canonical instance of the block device used for interacting with external memory + * without interfering with the region reserved for the WiFi firmware. + * + * This block device and the overrides that use it will only be defined if the macro CY_EXT_WIFI_FW_STORAGE is defined. + * If it is, then its value is used by to determine the default block device for accessing + * the external storage where the WiFi firmware is located. + * See cy_get_ext_wifi_fw_reserved_region_underlying_bd() for more details. + * + * In order to store the WiFi firmware in external storage at all, the macro CY_ENABLE_XIP_PROGRAM must be defined. + * Further, the macro CY_STORAGE_WIFI_DATA must be set to the name of the input section where the WiFi firmware is + * to be placed, with surrounding quotation marks. The macro CY_STORAGE_WIFI_DATA_OUTPUT must be set to the name of the + * output section that the linker script places the input section in, without quotation marks. The name of this output + * section must not contain a '.' character. + * + * Using XIP by adding the xip-enable configuration override will prevent any of this from begin defined. + * + * @return A pointer to the canonical instance of the block device + */ +CyReservedRegionBlockDevice *cy_get_ext_wifi_fw_reserved_region_bd(); + +/** + * Modify the location and size of the WiFi firmware image/CLM blob. + * + * If the WiFi firmware is ever updated, this function must be called afterward as well as + * on every startup as long as the updated firmware continues to be used. + * The defaults are the initial locations and sizes on compilation. + * New firmware end should not exceed the initial end of the WiFi firmware output section + * so that storage mechanisms keep a consistent storage region. + * + * @param image_addr[in] New address of the WiFi firmware image + * @param image_size[in] New size of the WiFi firmware image + * @param clm_blob_addr[in] New address of the CLM blob + * @param clm_blob_size[in] New size of the CLM blob + * @return 0 on success, negative on failure + */ +int cy_update_ext_wifi_fw_location_and_size(mbed::bd_addr_t image_addr, mbed::bd_size_t image_size, mbed::bd_addr_t clm_blob_addr, mbed::bd_size_t clm_blob_size); + +#endif /* defined(CY_EXT_WIFI_FW_STORAGE) && !MBED_CONF_TARGET_XIP_ENABLE */ + +#endif /* CY_EXT_WIFI_FW_RESERVED_REGION_BD_H */ diff --git a/targets/TARGET_Cypress/TARGET_PSOC6/common/ext-wifi-fw/cy_ext_wifi_fw_resources.c b/targets/TARGET_Cypress/TARGET_PSOC6/common/ext-wifi-fw/cy_ext_wifi_fw_resources.c new file mode 100644 index 0000000000..332c4e018e --- /dev/null +++ b/targets/TARGET_Cypress/TARGET_PSOC6/common/ext-wifi-fw/cy_ext_wifi_fw_resources.c @@ -0,0 +1,322 @@ +/***************************************************************************//** +* \file cy_ext_wifi_fw_resources.c +* +* \brief +* Defines resource functions for BCM943340WCD1 platform adapted to work with WiFi firmware storage in external memory. +* +******************************************************************************** +* \copyright +* Copyright 2020 Cypress Semiconductor Corporation +* SPDX-License-Identifier: Apache-2.0 +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*******************************************************************************/ + +#if defined(CY_EXT_WIFI_FW_STORAGE) && !MBED_CONF_TARGET_XIP_ENABLE + +#if defined(__cplusplus) +extern "C" { +#endif + +#include "resources.h" +#include "wifi_nvram_image.h" +#include "whd_resource_api.h" +#include "whd_debug.h" +#include "whd.h" +#include "cy_wifi_fw_section.h" + +/****************************************************** +* Macros +******************************************************/ +#define BLOCK_BUFFER_SIZE (1024) + +/****************************************************** +* Constants +******************************************************/ + +#if defined(WHD_DYNAMIC_NVRAM) +#define NVRAM_SIZE dynamic_nvram_size +#define NVRAM_IMAGE_VARIABLE dynamic_nvram_image +#else +#define NVRAM_SIZE sizeof(wifi_nvram_image) +#define NVRAM_IMAGE_VARIABLE wifi_nvram_image +#endif + +/****************************************************** +* Enumerations +******************************************************/ + +/****************************************************** +* Type Definitions +******************************************************/ + +/****************************************************** +* Structures +******************************************************/ + +/****************************************************** +* Static Function Declarations +******************************************************/ +uint32_t ext_wifi_fw_host_get_resource_block(whd_driver_t whd_drv, whd_resource_type_t type, + uint32_t blockno, const uint8_t **data, uint32_t *size_out); +resource_result_t ext_wifi_fw_resource_read(const resource_hnd_t *resource, uint32_t offset, uint32_t maxsize, uint32_t *size, + void *buffer); + +extern uint32_t host_platform_resource_size(whd_driver_t whd_drv, whd_resource_type_t resource, uint32_t *size_out); +extern uint32_t host_get_resource_block_size(whd_driver_t whd_drv, whd_resource_type_t type, uint32_t *size_out); +extern uint32_t host_get_resource_no_of_blocks(whd_driver_t whd_drv, whd_resource_type_t type, uint32_t *block_count); + +/****************************************************** +* Variable Definitions +******************************************************/ + +#ifdef WLAN_MFG_FIRMWARE + +extern const resource_hnd_t wifi_mfg_firmware_image; +extern const resource_hnd_t wifi_mfg_firmware_clm_blob; + +static resource_hnd_t wifi_mfg_firmware_image_external; +static resource_hnd_t wifi_mfg_firmware_clm_blob_external; +#define WIFI_FIRMWARE_IMAGE wifi_mfg_firmware_image_external +#define WIFI_FIRMWARE_CLM_BLOB wifi_mfg_firmware_clm_blob_external + +#else + +extern const resource_hnd_t wifi_firmware_image; +extern const resource_hnd_t wifi_firmware_clm_blob; + +static resource_hnd_t wifi_firmware_image_external; +static resource_hnd_t wifi_firmware_clm_blob_external; +#define WIFI_FIRMWARE_IMAGE wifi_firmware_image_external +#define WIFI_FIRMWARE_CLM_BLOB wifi_firmware_clm_blob_external + +#endif + +static bool external_handles_initialized = false; + +extern resource_result_t platform_read_external_resource(const resource_hnd_t *resource, uint32_t offset, uint32_t maxsize, uint32_t *size, void *buffer); + +unsigned char whd_r_buffer[BLOCK_BUFFER_SIZE]; + +#if defined(WHD_DYNAMIC_NVRAM) +uint32_t dynamic_nvram_size = sizeof(wifi_nvram_image); +void *dynamic_nvram_image = &wifi_nvram_image; +#endif + +/****************************************************** +* Function Definitions +******************************************************/ + +void try_init_external_handles() +{ + if (!external_handles_initialized) + { +#if defined(WLAN_MFG_FIRMWARE) + wifi_mfg_firmware_image_external = (resource_hnd_t){ + RESOURCE_IN_EXTERNAL_STORAGE, + wifi_mfg_firmware_image.size, + { .external_storage_context = (void *) (wifi_mfg_firmware_image.val.mem.data - (uint32_t) CY_WIFI_FW_SECTION_START) } + }; + wifi_mfg_firmware_clm_blob_external = (resource_hnd_t){ + RESOURCE_IN_EXTERNAL_STORAGE, + wifi_mfg_firmware_clm_blob.size, + { .external_storage_context = (void *) (wifi_mfg_firmware_clm_blob.val.mem.data - (uint32_t) CY_WIFI_FW_SECTION_START) } + }; +#else + wifi_firmware_image_external = (resource_hnd_t){ + RESOURCE_IN_EXTERNAL_STORAGE, + wifi_firmware_image.size, + { .external_storage_context = (void *) (wifi_firmware_image.val.mem.data - (uint32_t) CY_WIFI_FW_SECTION_START) } + }; + wifi_firmware_clm_blob_external = (resource_hnd_t){ + RESOURCE_IN_EXTERNAL_STORAGE, + wifi_firmware_clm_blob.size, + { .external_storage_context = (void *) (wifi_firmware_clm_blob.val.mem.data - (uint32_t) CY_WIFI_FW_SECTION_START) } + }; +#endif /* defined(WLAN_MFG_FIRMWARE) */ + external_handles_initialized = true; + } +} + +void cy_ext_wifi_fw_resources_update_handles(void *image_addr, unsigned long image_size, void *clm_blob_addr, unsigned long clm_blob_size) +{ + WIFI_FIRMWARE_IMAGE.val.external_storage_context = image_addr; + WIFI_FIRMWARE_IMAGE.size = image_size; + + WIFI_FIRMWARE_CLM_BLOB.val.external_storage_context = clm_blob_addr; + WIFI_FIRMWARE_CLM_BLOB.size = clm_blob_size; +} + +resource_result_t ext_wifi_fw_resource_read(const resource_hnd_t *resource, uint32_t offset, uint32_t maxsize, uint32_t *size, + void *buffer) +{ + if (offset > resource->size) + { + return RESOURCE_OFFSET_TOO_BIG; + } + + *size = MIN(maxsize, resource->size - offset); + + if (resource->location == RESOURCE_IN_MEMORY) + { + memcpy(buffer, &resource->val.mem.data[offset], *size); + } + else if (resource->location == RESOURCE_IN_EXTERNAL_STORAGE) + { + return platform_read_external_resource(resource, offset, maxsize, size, buffer); + } +#ifdef USES_RESOURCE_GENERIC_FILESYSTEM + else + { + wiced_file_t file_handle; + uint64_t size64; + uint64_t maxsize64 = maxsize; + if (WICED_SUCCESS != + wiced_filesystem_file_open (&resource_fs_handle, &file_handle, resource->val.fs.filename, + WICED_FILESYSTEM_OPEN_FOR_READ) ) + { + return RESOURCE_FILE_OPEN_FAIL; + } + if (WICED_SUCCESS != wiced_filesystem_file_seek (&file_handle, (offset + resource->val.fs.offset), SEEK_SET) ) + { + return RESOURCE_FILE_SEEK_FAIL; + } + if (WICED_SUCCESS != wiced_filesystem_file_read (&file_handle, buffer, maxsize64, &size64) ) + { + wiced_filesystem_file_close (&file_handle); + return RESOURCE_FILE_READ_FAIL; + } + *size = (uint32_t)size64; + wiced_filesystem_file_close (&file_handle); + } +#else +#ifdef USES_RESOURCE_FILESYSTEM + else + { + wicedfs_file_t file_hnd; + + if (0 != wicedfs_fopen(&resource_fs_handle, &file_hnd, resource->val.fs.filename) ) + { + return RESOURCE_FILE_OPEN_FAIL; + } + + if (0 != wicedfs_fseek(&file_hnd, (long)(offset + resource->val.fs.offset), SEEK_SET) ) + { + wicedfs_fclose(&file_hnd); + return RESOURCE_FILE_SEEK_FAIL; + } + + if (*size != wicedfs_fread(buffer, 1, *size, &file_hnd) ) + { + wicedfs_fclose(&file_hnd); + return RESOURCE_FILE_READ_FAIL; + } + + wicedfs_fclose(&file_hnd); + } +#endif /* ifdef USES_RESOURCE_FILESYSTEM */ +#endif /* USES_RESOURCE_GENERIC_FILESYSTEM */ + return RESOURCE_SUCCESS; +} + +uint32_t ext_wifi_fw_host_get_resource_block(whd_driver_t whd_drv, whd_resource_type_t type, + uint32_t blockno, const uint8_t **data, uint32_t *size_out) +{ + uint32_t resource_size; + uint32_t block_size; + uint32_t block_count; + uint32_t read_pos; + uint32_t result; + + try_init_external_handles(); + + host_platform_resource_size(whd_drv, type, &resource_size); + host_get_resource_block_size(whd_drv, type, &block_size); + host_get_resource_no_of_blocks(whd_drv, type, &block_count); + memset(whd_r_buffer, 0, block_size); + read_pos = blockno * block_size; + + if (blockno >= block_count) + { + return WHD_BADARG; + } + + if (type == WHD_RESOURCE_WLAN_FIRMWARE) + { + result = ext_wifi_fw_resource_read( (const resource_hnd_t *)&WIFI_FIRMWARE_IMAGE, read_pos, block_size, size_out, + whd_r_buffer ); + if (result != WHD_SUCCESS) + { + return result; + } + *data = (uint8_t *)&whd_r_buffer; + /* + * In case of local buffer read use the following code + * + * *size_out = MIN(BLOCK_BUFFER_SIZE, resource_size - transfer_progress); + * *data = (uint8_t *)wifi_firmware_image_data; + * + * For sending the entire buffer in single block set size out as following + * *size_out = (uint32_t)resource_get_size(&wifi_firmware_image); + */ + } + else if (type == WHD_RESOURCE_WLAN_NVRAM) + { + if (NVRAM_SIZE - read_pos > block_size) + { + *size_out = block_size; + } + else + { + *size_out = NVRAM_SIZE - read_pos; + } + *data = ( (uint8_t *)NVRAM_IMAGE_VARIABLE ) + read_pos; + } + else + { + result = ext_wifi_fw_resource_read( (const resource_hnd_t *)&WIFI_FIRMWARE_CLM_BLOB, read_pos, block_size, + size_out, + whd_r_buffer ); + if (result != WHD_SUCCESS) + { + return result; + } + *data = (uint8_t *)&whd_r_buffer; + /* + * In case of local buffer read use the following code + * + * *size_out = MIN(BLOCK_BUFFER_SIZE, resource_size - transfer_progress); + * *data = (uint8_t *)wifi_firmware_clm_blob_image_data; + * + * For sending the entire buffer in single block set size out as following + * *size_out = sizeof(wifi_firmware_clm_blob_image_data); + */ + + } + + return WHD_SUCCESS; +} + +whd_resource_source_t cy_ext_wifi_fw_resource_ops = +{ + .whd_resource_size = host_platform_resource_size, + .whd_get_resource_block_size = host_get_resource_block_size, + .whd_get_resource_no_of_blocks = host_get_resource_no_of_blocks, + .whd_get_resource_block = ext_wifi_fw_host_get_resource_block +}; + +#if defined(__cplusplus) +} +#endif + +#endif /* defined(CY_EXT_WIFI_FW_STORAGE) && !MBED_CONF_TARGET_XIP_ENABLE */