@@ -175,10 +175,10 @@ qla2x00_sysfs_read_optrom(struct kobject *kobj,
175
175
176
176
if (ha -> optrom_state != QLA_SREADING )
177
177
return 0 ;
178
- if (off > ha -> optrom_size )
178
+ if (off > ha -> optrom_region_size )
179
179
return 0 ;
180
- if (off + count > ha -> optrom_size )
181
- count = ha -> optrom_size - off ;
180
+ if (off + count > ha -> optrom_region_size )
181
+ count = ha -> optrom_region_size - off ;
182
182
183
183
memcpy (buf , & ha -> optrom_buffer [off ], count );
184
184
@@ -195,10 +195,10 @@ qla2x00_sysfs_write_optrom(struct kobject *kobj,
195
195
196
196
if (ha -> optrom_state != QLA_SWRITING )
197
197
return - EINVAL ;
198
- if (off > ha -> optrom_size )
198
+ if (off > ha -> optrom_region_size )
199
199
return - ERANGE ;
200
- if (off + count > ha -> optrom_size )
201
- count = ha -> optrom_size - off ;
200
+ if (off + count > ha -> optrom_region_size )
201
+ count = ha -> optrom_region_size - off ;
202
202
203
203
memcpy (& ha -> optrom_buffer [off ], buf , count );
204
204
@@ -222,12 +222,16 @@ qla2x00_sysfs_write_optrom_ctl(struct kobject *kobj,
222
222
{
223
223
struct scsi_qla_host * ha = to_qla_host (dev_to_shost (container_of (kobj ,
224
224
struct device , kobj )));
225
- int val ;
225
+ uint32_t start = 0 ;
226
+ uint32_t size = ha -> optrom_size ;
227
+ int val , valid ;
226
228
227
229
if (off )
228
230
return 0 ;
229
231
230
- if (sscanf (buf , "%d" , & val ) != 1 )
232
+ if (sscanf (buf , "%d:%x:%x" , & val , & start , & size ) < 1 )
233
+ return - EINVAL ;
234
+ if (start > ha -> optrom_size )
231
235
return - EINVAL ;
232
236
233
237
switch (val ) {
@@ -237,51 +241,119 @@ qla2x00_sysfs_write_optrom_ctl(struct kobject *kobj,
237
241
break ;
238
242
239
243
ha -> optrom_state = QLA_SWAITING ;
244
+
245
+ DEBUG2 (qla_printk (KERN_INFO , ha ,
246
+ "Freeing flash region allocation -- 0x%x bytes.\n" ,
247
+ ha -> optrom_region_size ));
248
+
240
249
vfree (ha -> optrom_buffer );
241
250
ha -> optrom_buffer = NULL ;
242
251
break ;
243
252
case 1 :
244
253
if (ha -> optrom_state != QLA_SWAITING )
245
254
break ;
246
255
256
+ if (start & 0xfff ) {
257
+ qla_printk (KERN_WARNING , ha ,
258
+ "Invalid start region 0x%x/0x%x.\n" , start , size );
259
+ return - EINVAL ;
260
+ }
261
+
262
+ ha -> optrom_region_start = start ;
263
+ ha -> optrom_region_size = start + size > ha -> optrom_size ?
264
+ ha -> optrom_size - start : size ;
265
+
247
266
ha -> optrom_state = QLA_SREADING ;
248
- ha -> optrom_buffer = ( uint8_t * ) vmalloc (ha -> optrom_size );
267
+ ha -> optrom_buffer = vmalloc (ha -> optrom_region_size );
249
268
if (ha -> optrom_buffer == NULL ) {
250
269
qla_printk (KERN_WARNING , ha ,
251
270
"Unable to allocate memory for optrom retrieval "
252
- "(%x).\n" , ha -> optrom_size );
271
+ "(%x).\n" , ha -> optrom_region_size );
253
272
254
273
ha -> optrom_state = QLA_SWAITING ;
255
274
return count ;
256
275
}
257
276
258
- memset (ha -> optrom_buffer , 0 , ha -> optrom_size );
259
- ha -> isp_ops -> read_optrom (ha , ha -> optrom_buffer , 0 ,
260
- ha -> optrom_size );
277
+ DEBUG2 (qla_printk (KERN_INFO , ha ,
278
+ "Reading flash region -- 0x%x/0x%x.\n" ,
279
+ ha -> optrom_region_start , ha -> optrom_region_size ));
280
+
281
+ memset (ha -> optrom_buffer , 0 , ha -> optrom_region_size );
282
+ ha -> isp_ops -> read_optrom (ha , ha -> optrom_buffer ,
283
+ ha -> optrom_region_start , ha -> optrom_region_size );
261
284
break ;
262
285
case 2 :
263
286
if (ha -> optrom_state != QLA_SWAITING )
264
287
break ;
265
288
289
+ /*
290
+ * We need to be more restrictive on which FLASH regions are
291
+ * allowed to be updated via user-space. Regions accessible
292
+ * via this method include:
293
+ *
294
+ * ISP21xx/ISP22xx/ISP23xx type boards:
295
+ *
296
+ * 0x000000 -> 0x020000 -- Boot code.
297
+ *
298
+ * ISP2322/ISP24xx type boards:
299
+ *
300
+ * 0x000000 -> 0x07ffff -- Boot code.
301
+ * 0x080000 -> 0x0fffff -- Firmware.
302
+ *
303
+ * ISP25xx type boards:
304
+ *
305
+ * 0x000000 -> 0x07ffff -- Boot code.
306
+ * 0x080000 -> 0x0fffff -- Firmware.
307
+ * 0x120000 -> 0x12ffff -- VPD and HBA parameters.
308
+ */
309
+ valid = 0 ;
310
+ if (ha -> optrom_size == OPTROM_SIZE_2300 && start == 0 )
311
+ valid = 1 ;
312
+ else if (start == (FA_BOOT_CODE_ADDR * 4 ) ||
313
+ start == (FA_RISC_CODE_ADDR * 4 ))
314
+ valid = 1 ;
315
+ else if (IS_QLA25XX (ha ) && start == (FA_VPD_NVRAM_ADDR * 4 ))
316
+ valid = 1 ;
317
+ if (!valid ) {
318
+ qla_printk (KERN_WARNING , ha ,
319
+ "Invalid start region 0x%x/0x%x.\n" , start , size );
320
+ return - EINVAL ;
321
+ }
322
+
323
+ ha -> optrom_region_start = start ;
324
+ ha -> optrom_region_size = start + size > ha -> optrom_size ?
325
+ ha -> optrom_size - start : size ;
326
+
266
327
ha -> optrom_state = QLA_SWRITING ;
267
- ha -> optrom_buffer = ( uint8_t * ) vmalloc (ha -> optrom_size );
328
+ ha -> optrom_buffer = vmalloc (ha -> optrom_region_size );
268
329
if (ha -> optrom_buffer == NULL ) {
269
330
qla_printk (KERN_WARNING , ha ,
270
331
"Unable to allocate memory for optrom update "
271
- "(%x).\n" , ha -> optrom_size );
332
+ "(%x).\n" , ha -> optrom_region_size );
272
333
273
334
ha -> optrom_state = QLA_SWAITING ;
274
335
return count ;
275
336
}
276
- memset (ha -> optrom_buffer , 0 , ha -> optrom_size );
337
+
338
+ DEBUG2 (qla_printk (KERN_INFO , ha ,
339
+ "Staging flash region write -- 0x%x/0x%x.\n" ,
340
+ ha -> optrom_region_start , ha -> optrom_region_size ));
341
+
342
+ memset (ha -> optrom_buffer , 0 , ha -> optrom_region_size );
277
343
break ;
278
344
case 3 :
279
345
if (ha -> optrom_state != QLA_SWRITING )
280
346
break ;
281
347
282
- ha -> isp_ops -> write_optrom (ha , ha -> optrom_buffer , 0 ,
283
- ha -> optrom_size );
348
+ DEBUG2 (qla_printk (KERN_INFO , ha ,
349
+ "Writing flash region -- 0x%x/0x%x.\n" ,
350
+ ha -> optrom_region_start , ha -> optrom_region_size ));
351
+
352
+ ha -> isp_ops -> write_optrom (ha , ha -> optrom_buffer ,
353
+ ha -> optrom_region_start , ha -> optrom_region_size );
284
354
break ;
355
+ default :
356
+ count = - EINVAL ;
285
357
}
286
358
return count ;
287
359
}
0 commit comments