1 /*
2  * Copyright 2023, Cypress Semiconductor Corporation (an Infineon company)
3  * SPDX-License-Identifier: Apache-2.0
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *     http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17 
18 /** @file
19  * Defines WHD resource functions for BCM943340WCD1 platform
20  */
21 #include "cmsis_compiler.h"
22 #include "cy_utils.h"
23 #include "resources.h"
24 #include "clm_resources.h"
25 #include "wifi_nvram_image.h"
26 #include "whd_resource_api.h"
27 #include "whd_debug.h"
28 #include "whd.h"
29 
30 /******************************************************
31 *                      Macros
32 ******************************************************/
33 #define BLOCK_BUFFER_SIZE                    (1024)
34 
35 /******************************************************
36 *                    Constants
37 ******************************************************/
38 
39 #if defined(WHD_DYNAMIC_NVRAM)
40 #define NVRAM_SIZE             dynamic_nvram_size
41 #define NVRAM_IMAGE_VARIABLE   dynamic_nvram_image
42 #else
43 #define NVRAM_SIZE             sizeof(wifi_nvram_image)
44 #define NVRAM_IMAGE_VARIABLE   wifi_nvram_image
45 #endif
46 
47 /******************************************************
48 *                   Enumerations
49 ******************************************************/
50 
51 /******************************************************
52 *                 Type Definitions
53 ******************************************************/
54 
55 /******************************************************
56 *                    Structures
57 ******************************************************/
58 
59 /******************************************************
60 *               Static Function Declarations
61 ******************************************************/
62 uint32_t host_platform_resource_size(whd_driver_t whd_drv, whd_resource_type_t resource, uint32_t *size_out);
63 uint32_t host_get_resource_block(whd_driver_t whd_drv, whd_resource_type_t type,
64                                  uint32_t blockno, const uint8_t **data, uint32_t *size_out);
65 uint32_t host_get_resource_no_of_blocks(whd_driver_t whd_drv, whd_resource_type_t type, uint32_t *block_count);
66 uint32_t host_get_resource_block_size(whd_driver_t whd_drv, whd_resource_type_t type, uint32_t *size_out);
67 resource_result_t resource_read(const resource_hnd_t *resource, uint32_t offset, uint32_t maxsize, uint32_t *size,
68                                 void *buffer);
69 uint32_t host_resource_read(whd_driver_t whd_drv, whd_resource_type_t type,
70                             uint32_t offset, uint32_t size, uint32_t *size_out, void *buffer);
71 /******************************************************
72 *               Variable Definitions
73 ******************************************************/
74 
75 #ifdef WLAN_MFG_FIRMWARE
76 extern const resource_hnd_t wifi_mfg_firmware_image;
77 extern const resource_hnd_t wifi_mfg_firmware_clm_blob;
78 #else
79 extern const resource_hnd_t wifi_firmware_image;
80 extern const resource_hnd_t wifi_firmware_clm_blob;
81 #endif
82 
83 // Need to be aligned as whd_bus_spi_protocol.c reads a uint32_t
84 CY_ALIGN(4) unsigned char r_buffer[BLOCK_BUFFER_SIZE];
85 
86 #if defined(WHD_DYNAMIC_NVRAM)
87 uint32_t dynamic_nvram_size = sizeof(wifi_nvram_image);
88 void *dynamic_nvram_image = &wifi_nvram_image;
89 #endif
90 
91 /******************************************************
92 *               Function Definitions
93 ******************************************************/
94 
resource_read(const resource_hnd_t * resource,uint32_t offset,uint32_t maxsize,uint32_t * size,void * buffer)95 resource_result_t resource_read(const resource_hnd_t *resource, uint32_t offset, uint32_t maxsize, uint32_t *size,
96                                 void *buffer)
97 {
98     if (offset > resource->size)
99     {
100         return RESOURCE_OFFSET_TOO_BIG;
101     }
102 
103     *size = MIN(maxsize, resource->size - offset);
104 
105     if (resource->location == RESOURCE_IN_MEMORY)
106     {
107         memcpy(buffer, &resource->val.mem.data[offset], *size);
108     }
109 #ifdef USES_RESOURCES_IN_EXTERNAL_STORAGE
110     else if (resource->location == RESOURCE_IN_EXTERNAL_STORAGE)
111     {
112         return platform_read_external_resource(resource, offset, maxsize, size, buffer);
113     }
114 #endif
115 #ifdef USES_RESOURCE_GENERIC_FILESYSTEM
116     else
117     {
118         wiced_file_t file_handle;
119         uint64_t size64;
120         uint64_t maxsize64 =  maxsize;
121         if (WICED_SUCCESS !=
122             wiced_filesystem_file_open (&resource_fs_handle, &file_handle, resource->val.fs.filename,
123                                         WICED_FILESYSTEM_OPEN_FOR_READ) )
124         {
125             return RESOURCE_FILE_OPEN_FAIL;
126         }
127         if (WICED_SUCCESS != wiced_filesystem_file_seek (&file_handle, (offset + resource->val.fs.offset), SEEK_SET) )
128         {
129             return RESOURCE_FILE_SEEK_FAIL;
130         }
131         if (WICED_SUCCESS != wiced_filesystem_file_read (&file_handle, buffer, maxsize64, &size64) )
132         {
133             wiced_filesystem_file_close (&file_handle);
134             return RESOURCE_FILE_READ_FAIL;
135         }
136         *size = (uint32_t)size64;
137         wiced_filesystem_file_close (&file_handle);
138     }
139 #else
140 #ifdef USES_RESOURCE_FILESYSTEM
141     else
142     {
143         wicedfs_file_t file_hnd;
144 
145         if (0 != wicedfs_fopen(&resource_fs_handle, &file_hnd, resource->val.fs.filename) )
146         {
147             return RESOURCE_FILE_OPEN_FAIL;
148         }
149 
150         if (0 != wicedfs_fseek(&file_hnd, (long)(offset + resource->val.fs.offset), SEEK_SET) )
151         {
152             wicedfs_fclose(&file_hnd);
153             return RESOURCE_FILE_SEEK_FAIL;
154         }
155 
156         if (*size != wicedfs_fread(buffer, 1, *size, &file_hnd) )
157         {
158             wicedfs_fclose(&file_hnd);
159             return RESOURCE_FILE_READ_FAIL;
160         }
161 
162         wicedfs_fclose(&file_hnd);
163     }
164 #endif /* ifdef USES_RESOURCE_FILESYSTEM */
165 #endif /* USES_RESOURCE_GENERIC_FILESYSTEM */
166     return RESOURCE_SUCCESS;
167 }
168 
host_platform_resource_size(whd_driver_t whd_drv,whd_resource_type_t resource,uint32_t * size_out)169 uint32_t host_platform_resource_size(whd_driver_t whd_drv, whd_resource_type_t resource, uint32_t *size_out)
170 {
171     if (resource == WHD_RESOURCE_WLAN_FIRMWARE)
172     {
173 #ifdef NO_WIFI_FIRMWARE
174         whd_assert("Request firmware in a no wifi firmware application", 0 == 1);
175         *size_out = 0;
176 #else
177 #ifdef WIFI_FIRMWARE_IN_MULTI_APP
178         wiced_app_t wifi_app;
179 
180         *size_out = 0;
181         if (wiced_waf_app_open(DCT_WIFI_FIRMWARE_INDEX, &wifi_app) != WICED_SUCCESS)
182         {
183             return ( whd_result_t )RESOURCE_UNSUPPORTED;
184         }
185         wiced_waf_app_get_size(&wifi_app, size_out);
186 #else
187 #ifdef WLAN_MFG_FIRMWARE
188         *size_out = (uint32_t)resource_get_size(&wifi_mfg_firmware_image);
189 #else
190         *size_out = (uint32_t)resource_get_size(&wifi_firmware_image);
191 #endif /* WLAN_MFG_FIRMWARE */
192 #endif /* WIFI_FIRMWARE_IN_MULTI_APP */
193 #endif /* NO_WIFI_FIRMWARE */
194 
195     }
196     else if (resource == WHD_RESOURCE_WLAN_NVRAM)
197     {
198         *size_out = NVRAM_SIZE;
199     }
200     else
201     {
202 #ifdef WLAN_MFG_FIRMWARE
203         *size_out = (uint32_t)resource_get_size(&wifi_mfg_firmware_clm_blob);
204 #else
205         *size_out = (uint32_t)resource_get_size(&wifi_firmware_clm_blob);
206 #endif /* WLAN_MFG_FIRMWARE */
207     }
208     return WHD_SUCCESS;
209 }
210 
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)211 uint32_t host_get_resource_block(whd_driver_t whd_drv, whd_resource_type_t type,
212                                  uint32_t blockno, const uint8_t **data, uint32_t *size_out)
213 {
214     uint32_t resource_size;
215     uint32_t block_size;
216     uint32_t block_count;
217     uint32_t read_pos;
218     uint32_t result;
219 
220     host_platform_resource_size(whd_drv, type, &resource_size);
221     host_get_resource_block_size(whd_drv, type, &block_size);
222     host_get_resource_no_of_blocks(whd_drv, type, &block_count);
223     memset(r_buffer, 0, block_size);
224     read_pos = blockno * block_size;
225 
226     if (blockno >= block_count)
227     {
228         return WHD_BADARG;
229     }
230 
231     if (type == WHD_RESOURCE_WLAN_FIRMWARE)
232     {
233 #ifdef WLAN_MFG_FIRMWARE
234         result = resource_read( (const resource_hnd_t *)&wifi_mfg_firmware_image, read_pos, block_size, size_out,
235                                 r_buffer );
236 #else
237         result = resource_read( (const resource_hnd_t *)&wifi_firmware_image, read_pos, block_size, size_out,
238                                 r_buffer );
239 #endif /* WLAN_MFG_FIRMWARE */
240         if (result != WHD_SUCCESS)
241         {
242             return result;
243         }
244         *data = (uint8_t *)&r_buffer;
245         /*
246          * In case of local buffer read use the following code
247          *
248          *  *size_out = MIN(BLOCK_BUFFER_SIZE, resource_size - transfer_progress);
249          *  *data = (uint8_t *)wifi_firmware_image_data;
250          *
251          * For sending the entire buffer in single block set size out as following
252          *  *size_out = (uint32_t)resource_get_size(&wifi_firmware_image);
253          */
254     }
255     else if (type == WHD_RESOURCE_WLAN_NVRAM)
256     {
257         if (NVRAM_SIZE - read_pos > block_size)
258         {
259             *size_out = block_size;
260         }
261         else
262         {
263             *size_out = NVRAM_SIZE - read_pos;
264         }
265         *data = ( (uint8_t *)NVRAM_IMAGE_VARIABLE ) + read_pos;
266     }
267     else
268     {
269 #ifdef WLAN_MFG_FIRMWARE
270         result = resource_read( (const resource_hnd_t *)&wifi_mfg_firmware_clm_blob, read_pos, block_size,
271                                 size_out,
272                                 r_buffer );
273 #else
274         result = resource_read( (const resource_hnd_t *)&wifi_firmware_clm_blob, read_pos, block_size,
275                                 size_out,
276                                 r_buffer );
277 #endif /* WLAN_MFG_FIRMWARE */
278         if (result != WHD_SUCCESS)
279         {
280             return result;
281         }
282         *data = (uint8_t *)&r_buffer;
283         /*
284          * In case of local buffer read use the following code
285          *
286          *  *size_out = MIN(BLOCK_BUFFER_SIZE, resource_size - transfer_progress);
287          *  *data = (uint8_t *)wifi_firmware_clm_blob_image_data;
288          *
289          * For sending the entire buffer in single block set size out as following
290          *  *size_out = sizeof(wifi_firmware_clm_blob_image_data);
291          */
292 
293     }
294 
295     return WHD_SUCCESS;
296 }
297 
host_get_resource_block_size(whd_driver_t whd_drv,whd_resource_type_t type,uint32_t * size_out)298 uint32_t host_get_resource_block_size(whd_driver_t whd_drv, whd_resource_type_t type, uint32_t *size_out)
299 {
300     *size_out = BLOCK_BUFFER_SIZE;
301     return WHD_SUCCESS;
302 }
303 
host_get_resource_no_of_blocks(whd_driver_t whd_drv,whd_resource_type_t type,uint32_t * block_count)304 uint32_t host_get_resource_no_of_blocks(whd_driver_t whd_drv, whd_resource_type_t type, uint32_t *block_count)
305 {
306     uint32_t resource_size;
307     uint32_t block_size;
308 
309     host_platform_resource_size(whd_drv, type, &resource_size);
310     host_get_resource_block_size(whd_drv, type, &block_size);
311     *block_count = resource_size / block_size;
312     if (resource_size % block_size)
313         *block_count += 1;
314 
315     return WHD_SUCCESS;
316 }
317 
host_resource_read(whd_driver_t whd_drv,whd_resource_type_t type,uint32_t offset,uint32_t size,uint32_t * size_out,void * buffer)318 uint32_t host_resource_read(whd_driver_t whd_drv, whd_resource_type_t type,
319                             uint32_t offset, uint32_t size, uint32_t *size_out, void *buffer)
320 {
321     uint32_t result;
322 
323     if (type == WHD_RESOURCE_WLAN_FIRMWARE)
324     {
325 #ifdef WLAN_MFG_FIRMWARE
326         result = resource_read( (const resource_hnd_t *)&wifi_mfg_firmware_image, offset, size,
327                                 size_out, buffer );
328 #else
329         result = resource_read( (const resource_hnd_t *)&wifi_firmware_image, offset, size,
330                                 size_out, buffer );
331 #endif /* WLAN_MFG_FIRMWARE */
332 
333         if (result != WHD_SUCCESS)
334             return result;
335 
336     }
337     else if (type == WHD_RESOURCE_WLAN_NVRAM)
338     {
339         if (size != sizeof(wifi_nvram_image) )
340         {
341             return WHD_BUFFER_SIZE_SET_ERROR;
342         }
343         memcpy( (uint8_t *)buffer, wifi_nvram_image, sizeof(wifi_nvram_image) );
344         *size_out = sizeof(wifi_nvram_image);
345     }
346     return WHD_SUCCESS;
347 }
348 
349 whd_resource_source_t resource_ops =
350 {
351     .whd_resource_size = host_platform_resource_size,
352     .whd_get_resource_block_size = host_get_resource_block_size,
353     .whd_get_resource_no_of_blocks = host_get_resource_no_of_blocks,
354     .whd_get_resource_block = host_get_resource_block,
355     .whd_resource_read = host_resource_read
356 };
357 
358