9
9
*
10
10
* Author: Conor Dooley <[email protected] >
11
11
*/
12
+ #include <linux/cleanup.h>
12
13
#include <linux/debugfs.h>
13
14
#include <linux/firmware.h>
14
15
#include <linux/math.h>
71
72
#define AUTO_UPDATE_UPGRADE_DIRECTORY (AUTO_UPDATE_DIRECTORY_WIDTH * AUTO_UPDATE_UPGRADE_INDEX)
72
73
#define AUTO_UPDATE_BLANK_DIRECTORY (AUTO_UPDATE_DIRECTORY_WIDTH * AUTO_UPDATE_BLANK_INDEX)
73
74
#define AUTO_UPDATE_DIRECTORY_SIZE SZ_1K
74
- #define AUTO_UPDATE_RESERVED_SIZE SZ_1M
75
- #define AUTO_UPDATE_BITSTREAM_BASE (AUTO_UPDATE_DIRECTORY_SIZE + AUTO_UPDATE_RESERVED_SIZE)
75
+ #define AUTO_UPDATE_INFO_BASE AUTO_UPDATE_DIRECTORY_SIZE
76
+ #define AUTO_UPDATE_INFO_SIZE SZ_1M
77
+ #define AUTO_UPDATE_BITSTREAM_BASE (AUTO_UPDATE_DIRECTORY_SIZE + AUTO_UPDATE_INFO_SIZE)
76
78
77
79
#define AUTO_UPDATE_TIMEOUT_MS 60000
78
80
@@ -86,6 +88,17 @@ struct mpfs_auto_update_priv {
86
88
bool cancel_request ;
87
89
};
88
90
91
+ static bool mpfs_auto_update_is_bitstream_info (const u8 * data , u32 size )
92
+ {
93
+ if (size < 4 )
94
+ return false;
95
+
96
+ if (data [0 ] == 0x4d && data [1 ] == 0x43 && data [2 ] == 0x48 && data [3 ] == 0x50 )
97
+ return true;
98
+
99
+ return false;
100
+ }
101
+
89
102
static enum fw_upload_err mpfs_auto_update_prepare (struct fw_upload * fw_uploader , const u8 * data ,
90
103
u32 size )
91
104
{
@@ -162,28 +175,17 @@ static enum fw_upload_err mpfs_auto_update_poll_complete(struct fw_upload *fw_up
162
175
static int mpfs_auto_update_verify_image (struct fw_upload * fw_uploader )
163
176
{
164
177
struct mpfs_auto_update_priv * priv = fw_uploader -> dd_handle ;
165
- struct mpfs_mss_response * response ;
166
- struct mpfs_mss_msg * message ;
167
- u32 * response_msg ;
178
+ u32 * response_msg __free (kfree ) =
179
+ kzalloc (AUTO_UPDATE_FEATURE_RESP_SIZE * sizeof (* response_msg ), GFP_KERNEL );
180
+ struct mpfs_mss_response * response __free (kfree ) =
181
+ kzalloc (sizeof (struct mpfs_mss_response ), GFP_KERNEL );
182
+ struct mpfs_mss_msg * message __free (kfree ) =
183
+ kzalloc (sizeof (struct mpfs_mss_msg ), GFP_KERNEL );
168
184
int ret ;
169
185
170
- response_msg = devm_kzalloc (priv -> dev , AUTO_UPDATE_FEATURE_RESP_SIZE * sizeof (* response_msg ),
171
- GFP_KERNEL );
172
- if (!response_msg )
186
+ if (!response_msg || !response || !message )
173
187
return - ENOMEM ;
174
188
175
- response = devm_kzalloc (priv -> dev , sizeof (struct mpfs_mss_response ), GFP_KERNEL );
176
- if (!response ) {
177
- ret = - ENOMEM ;
178
- goto free_response_msg ;
179
- }
180
-
181
- message = devm_kzalloc (priv -> dev , sizeof (struct mpfs_mss_msg ), GFP_KERNEL );
182
- if (!message ) {
183
- ret = - ENOMEM ;
184
- goto free_response ;
185
- }
186
-
187
189
/*
188
190
* The system controller can verify that an image in the flash is valid.
189
191
* Rather than duplicate the check in this driver, call the relevant
@@ -205,31 +207,25 @@ static int mpfs_auto_update_verify_image(struct fw_upload *fw_uploader)
205
207
ret = mpfs_blocking_transaction (priv -> sys_controller , message );
206
208
if (ret | response -> resp_status ) {
207
209
dev_warn (priv -> dev , "Verification of Upgrade Image failed!\n" );
208
- ret = ret ? ret : - EBADMSG ;
209
- goto free_message ;
210
+ return ret ? ret : - EBADMSG ;
210
211
}
211
212
212
213
dev_info (priv -> dev , "Verification of Upgrade Image passed!\n" );
213
214
214
- free_message :
215
- devm_kfree (priv -> dev , message );
216
- free_response :
217
- devm_kfree (priv -> dev , response );
218
- free_response_msg :
219
- devm_kfree (priv -> dev , response_msg );
220
-
221
- return ret ;
215
+ return 0 ;
222
216
}
223
217
224
- static int mpfs_auto_update_set_image_address (struct mpfs_auto_update_priv * priv , char * buffer ,
218
+ static int mpfs_auto_update_set_image_address (struct mpfs_auto_update_priv * priv ,
225
219
u32 image_address , loff_t directory_address )
226
220
{
227
221
struct erase_info erase ;
228
- size_t erase_size = AUTO_UPDATE_DIRECTORY_SIZE ;
222
+ size_t erase_size = round_up ( AUTO_UPDATE_DIRECTORY_SIZE , ( u64 ) priv -> flash -> erasesize ) ;
229
223
size_t bytes_written = 0 , bytes_read = 0 ;
224
+ char * buffer __free (kfree ) = kzalloc (erase_size , GFP_KERNEL );
230
225
int ret ;
231
226
232
- erase_size = round_up (erase_size , (u64 )priv -> flash -> erasesize );
227
+ if (!buffer )
228
+ return - ENOMEM ;
233
229
234
230
erase .addr = AUTO_UPDATE_DIRECTORY_BASE ;
235
231
erase .len = erase_size ;
@@ -275,7 +271,7 @@ static int mpfs_auto_update_set_image_address(struct mpfs_auto_update_priv *priv
275
271
return ret ;
276
272
277
273
if (bytes_written != erase_size )
278
- return ret ;
274
+ return - EIO ;
279
275
280
276
return 0 ;
281
277
}
@@ -285,26 +281,36 @@ static int mpfs_auto_update_write_bitstream(struct fw_upload *fw_uploader, const
285
281
{
286
282
struct mpfs_auto_update_priv * priv = fw_uploader -> dd_handle ;
287
283
struct erase_info erase ;
288
- char * buffer ;
289
284
loff_t directory_address = AUTO_UPDATE_UPGRADE_DIRECTORY ;
290
285
size_t erase_size = AUTO_UPDATE_DIRECTORY_SIZE ;
291
286
size_t bytes_written = 0 ;
287
+ bool is_info = mpfs_auto_update_is_bitstream_info (data , size );
292
288
u32 image_address ;
293
289
int ret ;
294
290
295
291
erase_size = round_up (erase_size , (u64 )priv -> flash -> erasesize );
296
292
297
- image_address = AUTO_UPDATE_BITSTREAM_BASE +
298
- AUTO_UPDATE_UPGRADE_INDEX * priv -> size_per_bitstream ;
299
-
300
- buffer = devm_kzalloc (priv -> dev , erase_size , GFP_KERNEL );
301
- if (!buffer )
302
- return - ENOMEM ;
293
+ if (is_info )
294
+ image_address = AUTO_UPDATE_INFO_BASE ;
295
+ else
296
+ image_address = AUTO_UPDATE_BITSTREAM_BASE +
297
+ AUTO_UPDATE_UPGRADE_INDEX * priv -> size_per_bitstream ;
303
298
304
- ret = mpfs_auto_update_set_image_address (priv , buffer , image_address , directory_address );
305
- if (ret ) {
306
- dev_err (priv -> dev , "failed to set image address in the SPI directory: %d\n" , ret );
307
- goto out ;
299
+ /*
300
+ * For bitstream info, the descriptor is written to a fixed offset,
301
+ * so there is no need to set the image address.
302
+ */
303
+ if (!is_info ) {
304
+ ret = mpfs_auto_update_set_image_address (priv , image_address , directory_address );
305
+ if (ret ) {
306
+ dev_err (priv -> dev , "failed to set image address in the SPI directory: %d\n" , ret );
307
+ return ret ;
308
+ }
309
+ } else {
310
+ if (size > AUTO_UPDATE_INFO_SIZE ) {
311
+ dev_err (priv -> dev , "bitstream info exceeds permitted size\n" );
312
+ return - ENOSPC ;
313
+ }
308
314
}
309
315
310
316
/*
@@ -318,7 +324,7 @@ static int mpfs_auto_update_write_bitstream(struct fw_upload *fw_uploader, const
318
324
dev_info (priv -> dev , "Erasing the flash at address (0x%x)\n" , image_address );
319
325
ret = mtd_erase (priv -> flash , & erase );
320
326
if (ret )
321
- goto out ;
327
+ return ret ;
322
328
323
329
/*
324
330
* No parsing etc of the bitstream is required. The system controller
@@ -328,18 +334,15 @@ static int mpfs_auto_update_write_bitstream(struct fw_upload *fw_uploader, const
328
334
dev_info (priv -> dev , "Writing the image to the flash at address (0x%x)\n" , image_address );
329
335
ret = mtd_write (priv -> flash , (loff_t )image_address , size , & bytes_written , data );
330
336
if (ret )
331
- goto out ;
337
+ return ret ;
332
338
333
- if (bytes_written != size ) {
334
- ret = - EIO ;
335
- goto out ;
336
- }
339
+ if (bytes_written != size )
340
+ return - EIO ;
337
341
338
342
* written = bytes_written ;
343
+ dev_info (priv -> dev , "Wrote 0x%zx bytes to the flash\n" , bytes_written );
339
344
340
- out :
341
- devm_kfree (priv -> dev , buffer );
342
- return ret ;
345
+ return 0 ;
343
346
}
344
347
345
348
static enum fw_upload_err mpfs_auto_update_write (struct fw_upload * fw_uploader , const u8 * data ,
@@ -362,6 +365,9 @@ static enum fw_upload_err mpfs_auto_update_write(struct fw_upload *fw_uploader,
362
365
goto out ;
363
366
}
364
367
368
+ if (mpfs_auto_update_is_bitstream_info (data , size ))
369
+ goto out ;
370
+
365
371
ret = mpfs_auto_update_verify_image (fw_uploader );
366
372
if (ret )
367
373
err = FW_UPLOAD_ERR_FW_INVALID ;
@@ -381,23 +387,15 @@ static const struct fw_upload_ops mpfs_auto_update_ops = {
381
387
382
388
static int mpfs_auto_update_available (struct mpfs_auto_update_priv * priv )
383
389
{
384
- struct mpfs_mss_response * response ;
385
- struct mpfs_mss_msg * message ;
386
- u32 * response_msg ;
390
+ u32 * response_msg __free (kfree ) =
391
+ kzalloc (AUTO_UPDATE_FEATURE_RESP_SIZE * sizeof (* response_msg ), GFP_KERNEL );
392
+ struct mpfs_mss_response * response __free (kfree ) =
393
+ kzalloc (sizeof (struct mpfs_mss_response ), GFP_KERNEL );
394
+ struct mpfs_mss_msg * message __free (kfree ) =
395
+ kzalloc (sizeof (struct mpfs_mss_msg ), GFP_KERNEL );
387
396
int ret ;
388
397
389
- response_msg = devm_kzalloc (priv -> dev ,
390
- AUTO_UPDATE_FEATURE_RESP_SIZE * sizeof (* response_msg ),
391
- GFP_KERNEL );
392
- if (!response_msg )
393
- return - ENOMEM ;
394
-
395
- response = devm_kzalloc (priv -> dev , sizeof (struct mpfs_mss_response ), GFP_KERNEL );
396
- if (!response )
397
- return - ENOMEM ;
398
-
399
- message = devm_kzalloc (priv -> dev , sizeof (struct mpfs_mss_msg ), GFP_KERNEL );
400
- if (!message )
398
+ if (!response_msg || !response || !message )
401
399
return - ENOMEM ;
402
400
403
401
/*
0 commit comments