@@ -221,6 +221,19 @@ struct qsee_rsp_uefi_query_variable_info {
221
221
* alignment of 8 bytes (64 bits) for GUIDs. Our definition of efi_guid_t,
222
222
* however, has an alignment of 4 byte (32 bits). So far, this seems to work
223
223
* fine here. See also the comment on the typedef of efi_guid_t.
224
+ *
225
+ * Note: It looks like uefisecapp is quite picky about how the memory passed to
226
+ * it is structured and aligned. In particular the request/response setup used
227
+ * for QSEE_CMD_UEFI_GET_VARIABLE. While qcom_qseecom_app_send(), in theory,
228
+ * accepts separate buffers/addresses for the request and response parts, in
229
+ * practice, however, it seems to expect them to be both part of a larger
230
+ * contiguous block. We initially allocated separate buffers for the request
231
+ * and response but this caused the QSEE_CMD_UEFI_GET_VARIABLE command to
232
+ * either not write any response to the response buffer or outright crash the
233
+ * device. Therefore, we now allocate a single contiguous block of DMA memory
234
+ * for both and properly align the data using the macros below. In particular,
235
+ * request and response structs are aligned at 8 byte (via __reqdata_offs()),
236
+ * following the driver that this has been reverse-engineered from.
224
237
*/
225
238
#define qcuefi_buf_align_fields (fields ...) \
226
239
({ \
@@ -244,6 +257,12 @@ struct qsee_rsp_uefi_query_variable_info {
244
257
#define __array_offs (type , count , offset ) \
245
258
__field_impl(sizeof(type) * (count), __alignof__(type), offset)
246
259
260
+ #define __array_offs_aligned (type , count , align , offset ) \
261
+ __field_impl(sizeof(type) * (count), align, offset)
262
+
263
+ #define __reqdata_offs (size , offset ) \
264
+ __array_offs_aligned(u8, size, 8, offset)
265
+
247
266
#define __array (type , count ) __array_offs(type, count, NULL)
248
267
#define __field_offs (type , offset ) __array_offs(type, 1, offset)
249
268
#define __field (type ) __array_offs(type, 1, NULL)
@@ -277,10 +296,15 @@ static efi_status_t qsee_uefi_get_variable(struct qcuefi_client *qcuefi, const e
277
296
unsigned long buffer_size = * data_size ;
278
297
efi_status_t efi_status = EFI_SUCCESS ;
279
298
unsigned long name_length ;
299
+ dma_addr_t cmd_buf_dma ;
300
+ size_t cmd_buf_size ;
301
+ void * cmd_buf ;
280
302
size_t guid_offs ;
281
303
size_t name_offs ;
282
304
size_t req_size ;
283
305
size_t rsp_size ;
306
+ size_t req_offs ;
307
+ size_t rsp_offs ;
284
308
ssize_t status ;
285
309
286
310
if (!name || !guid )
@@ -304,17 +328,19 @@ static efi_status_t qsee_uefi_get_variable(struct qcuefi_client *qcuefi, const e
304
328
__array (u8 , buffer_size )
305
329
);
306
330
307
- req_data = kzalloc (req_size , GFP_KERNEL );
308
- if (!req_data ) {
331
+ cmd_buf_size = qcuefi_buf_align_fields (
332
+ __reqdata_offs (req_size , & req_offs )
333
+ __reqdata_offs (rsp_size , & rsp_offs )
334
+ );
335
+
336
+ cmd_buf = qseecom_dma_alloc (qcuefi -> client , cmd_buf_size , & cmd_buf_dma , GFP_KERNEL );
337
+ if (!cmd_buf ) {
309
338
efi_status = EFI_OUT_OF_RESOURCES ;
310
339
goto out ;
311
340
}
312
341
313
- rsp_data = kzalloc (rsp_size , GFP_KERNEL );
314
- if (!rsp_data ) {
315
- efi_status = EFI_OUT_OF_RESOURCES ;
316
- goto out_free_req ;
317
- }
342
+ req_data = cmd_buf + req_offs ;
343
+ rsp_data = cmd_buf + rsp_offs ;
318
344
319
345
req_data -> command_id = QSEE_CMD_UEFI_GET_VARIABLE ;
320
346
req_data -> data_size = buffer_size ;
@@ -332,7 +358,9 @@ static efi_status_t qsee_uefi_get_variable(struct qcuefi_client *qcuefi, const e
332
358
333
359
memcpy (((void * )req_data ) + req_data -> guid_offset , guid , req_data -> guid_size );
334
360
335
- status = qcom_qseecom_app_send (qcuefi -> client , req_data , req_size , rsp_data , rsp_size );
361
+ status = qcom_qseecom_app_send (qcuefi -> client ,
362
+ cmd_buf_dma + req_offs , req_size ,
363
+ cmd_buf_dma + rsp_offs , rsp_size );
336
364
if (status ) {
337
365
efi_status = EFI_DEVICE_ERROR ;
338
366
goto out_free ;
@@ -407,9 +435,7 @@ static efi_status_t qsee_uefi_get_variable(struct qcuefi_client *qcuefi, const e
407
435
memcpy (data , ((void * )rsp_data ) + rsp_data -> data_offset , rsp_data -> data_size );
408
436
409
437
out_free :
410
- kfree (rsp_data );
411
- out_free_req :
412
- kfree (req_data );
438
+ qseecom_dma_free (qcuefi -> client , cmd_buf_size , cmd_buf , cmd_buf_dma );
413
439
out :
414
440
return efi_status ;
415
441
}
@@ -422,10 +448,15 @@ static efi_status_t qsee_uefi_set_variable(struct qcuefi_client *qcuefi, const e
422
448
struct qsee_rsp_uefi_set_variable * rsp_data ;
423
449
efi_status_t efi_status = EFI_SUCCESS ;
424
450
unsigned long name_length ;
451
+ dma_addr_t cmd_buf_dma ;
452
+ size_t cmd_buf_size ;
453
+ void * cmd_buf ;
425
454
size_t name_offs ;
426
455
size_t guid_offs ;
427
456
size_t data_offs ;
428
457
size_t req_size ;
458
+ size_t req_offs ;
459
+ size_t rsp_offs ;
429
460
ssize_t status ;
430
461
431
462
if (!name || !guid )
@@ -450,17 +481,19 @@ static efi_status_t qsee_uefi_set_variable(struct qcuefi_client *qcuefi, const e
450
481
__array_offs (u8 , data_size , & data_offs )
451
482
);
452
483
453
- req_data = kzalloc (req_size , GFP_KERNEL );
454
- if (!req_data ) {
484
+ cmd_buf_size = qcuefi_buf_align_fields (
485
+ __reqdata_offs (req_size , & req_offs )
486
+ __reqdata_offs (sizeof (* rsp_data ), & rsp_offs )
487
+ );
488
+
489
+ cmd_buf = qseecom_dma_alloc (qcuefi -> client , cmd_buf_size , & cmd_buf_dma , GFP_KERNEL );
490
+ if (!cmd_buf ) {
455
491
efi_status = EFI_OUT_OF_RESOURCES ;
456
492
goto out ;
457
493
}
458
494
459
- rsp_data = kzalloc (sizeof (* rsp_data ), GFP_KERNEL );
460
- if (!rsp_data ) {
461
- efi_status = EFI_OUT_OF_RESOURCES ;
462
- goto out_free_req ;
463
- }
495
+ req_data = cmd_buf + req_offs ;
496
+ rsp_data = cmd_buf + rsp_offs ;
464
497
465
498
req_data -> command_id = QSEE_CMD_UEFI_SET_VARIABLE ;
466
499
req_data -> attributes = attributes ;
@@ -483,8 +516,9 @@ static efi_status_t qsee_uefi_set_variable(struct qcuefi_client *qcuefi, const e
483
516
if (data_size )
484
517
memcpy (((void * )req_data ) + req_data -> data_offset , data , req_data -> data_size );
485
518
486
- status = qcom_qseecom_app_send (qcuefi -> client , req_data , req_size , rsp_data ,
487
- sizeof (* rsp_data ));
519
+ status = qcom_qseecom_app_send (qcuefi -> client ,
520
+ cmd_buf_dma + req_offs , req_size ,
521
+ cmd_buf_dma + rsp_offs , sizeof (* rsp_data ));
488
522
if (status ) {
489
523
efi_status = EFI_DEVICE_ERROR ;
490
524
goto out_free ;
@@ -507,9 +541,7 @@ static efi_status_t qsee_uefi_set_variable(struct qcuefi_client *qcuefi, const e
507
541
}
508
542
509
543
out_free :
510
- kfree (rsp_data );
511
- out_free_req :
512
- kfree (req_data );
544
+ qseecom_dma_free (qcuefi -> client , cmd_buf_size , cmd_buf , cmd_buf_dma );
513
545
out :
514
546
return efi_status ;
515
547
}
@@ -521,10 +553,15 @@ static efi_status_t qsee_uefi_get_next_variable(struct qcuefi_client *qcuefi,
521
553
struct qsee_req_uefi_get_next_variable * req_data ;
522
554
struct qsee_rsp_uefi_get_next_variable * rsp_data ;
523
555
efi_status_t efi_status = EFI_SUCCESS ;
556
+ dma_addr_t cmd_buf_dma ;
557
+ size_t cmd_buf_size ;
558
+ void * cmd_buf ;
524
559
size_t guid_offs ;
525
560
size_t name_offs ;
526
561
size_t req_size ;
527
562
size_t rsp_size ;
563
+ size_t req_offs ;
564
+ size_t rsp_offs ;
528
565
ssize_t status ;
529
566
530
567
if (!name_size || !name || !guid )
@@ -545,17 +582,19 @@ static efi_status_t qsee_uefi_get_next_variable(struct qcuefi_client *qcuefi,
545
582
__array (* name , * name_size / sizeof (* name ))
546
583
);
547
584
548
- req_data = kzalloc (req_size , GFP_KERNEL );
549
- if (!req_data ) {
585
+ cmd_buf_size = qcuefi_buf_align_fields (
586
+ __reqdata_offs (req_size , & req_offs )
587
+ __reqdata_offs (rsp_size , & rsp_offs )
588
+ );
589
+
590
+ cmd_buf = qseecom_dma_alloc (qcuefi -> client , cmd_buf_size , & cmd_buf_dma , GFP_KERNEL );
591
+ if (!cmd_buf ) {
550
592
efi_status = EFI_OUT_OF_RESOURCES ;
551
593
goto out ;
552
594
}
553
595
554
- rsp_data = kzalloc (rsp_size , GFP_KERNEL );
555
- if (!rsp_data ) {
556
- efi_status = EFI_OUT_OF_RESOURCES ;
557
- goto out_free_req ;
558
- }
596
+ req_data = cmd_buf + req_offs ;
597
+ rsp_data = cmd_buf + rsp_offs ;
559
598
560
599
req_data -> command_id = QSEE_CMD_UEFI_GET_NEXT_VARIABLE ;
561
600
req_data -> guid_offset = guid_offs ;
@@ -572,7 +611,9 @@ static efi_status_t qsee_uefi_get_next_variable(struct qcuefi_client *qcuefi,
572
611
goto out_free ;
573
612
}
574
613
575
- status = qcom_qseecom_app_send (qcuefi -> client , req_data , req_size , rsp_data , rsp_size );
614
+ status = qcom_qseecom_app_send (qcuefi -> client ,
615
+ cmd_buf_dma + req_offs , req_size ,
616
+ cmd_buf_dma + rsp_offs , rsp_size );
576
617
if (status ) {
577
618
efi_status = EFI_DEVICE_ERROR ;
578
619
goto out_free ;
@@ -645,9 +686,7 @@ static efi_status_t qsee_uefi_get_next_variable(struct qcuefi_client *qcuefi,
645
686
}
646
687
647
688
out_free :
648
- kfree (rsp_data );
649
- out_free_req :
650
- kfree (req_data );
689
+ qseecom_dma_free (qcuefi -> client , cmd_buf_size , cmd_buf , cmd_buf_dma );
651
690
out :
652
691
return efi_status ;
653
692
}
@@ -659,26 +698,34 @@ static efi_status_t qsee_uefi_query_variable_info(struct qcuefi_client *qcuefi,
659
698
struct qsee_req_uefi_query_variable_info * req_data ;
660
699
struct qsee_rsp_uefi_query_variable_info * rsp_data ;
661
700
efi_status_t efi_status = EFI_SUCCESS ;
701
+ dma_addr_t cmd_buf_dma ;
702
+ size_t cmd_buf_size ;
703
+ void * cmd_buf ;
704
+ size_t req_offs ;
705
+ size_t rsp_offs ;
662
706
int status ;
663
707
664
- req_data = kzalloc (sizeof (* req_data ), GFP_KERNEL );
665
- if (!req_data ) {
708
+ cmd_buf_size = qcuefi_buf_align_fields (
709
+ __reqdata_offs (sizeof (* req_data ), & req_offs )
710
+ __reqdata_offs (sizeof (* rsp_data ), & rsp_offs )
711
+ );
712
+
713
+ cmd_buf = qseecom_dma_alloc (qcuefi -> client , cmd_buf_size , & cmd_buf_dma , GFP_KERNEL );
714
+ if (!cmd_buf ) {
666
715
efi_status = EFI_OUT_OF_RESOURCES ;
667
716
goto out ;
668
717
}
669
718
670
- rsp_data = kzalloc (sizeof (* rsp_data ), GFP_KERNEL );
671
- if (!rsp_data ) {
672
- efi_status = EFI_OUT_OF_RESOURCES ;
673
- goto out_free_req ;
674
- }
719
+ req_data = cmd_buf + req_offs ;
720
+ rsp_data = cmd_buf + rsp_offs ;
675
721
676
722
req_data -> command_id = QSEE_CMD_UEFI_QUERY_VARIABLE_INFO ;
677
723
req_data -> attributes = attr ;
678
724
req_data -> length = sizeof (* req_data );
679
725
680
- status = qcom_qseecom_app_send (qcuefi -> client , req_data , sizeof (* req_data ), rsp_data ,
681
- sizeof (* rsp_data ));
726
+ status = qcom_qseecom_app_send (qcuefi -> client ,
727
+ cmd_buf_dma + req_offs , sizeof (* req_data ),
728
+ cmd_buf_dma + rsp_offs , sizeof (* rsp_data ));
682
729
if (status ) {
683
730
efi_status = EFI_DEVICE_ERROR ;
684
731
goto out_free ;
@@ -711,9 +758,7 @@ static efi_status_t qsee_uefi_query_variable_info(struct qcuefi_client *qcuefi,
711
758
* max_variable_size = rsp_data -> max_variable_size ;
712
759
713
760
out_free :
714
- kfree (rsp_data );
715
- out_free_req :
716
- kfree (req_data );
761
+ qseecom_dma_free (qcuefi -> client , cmd_buf_size , cmd_buf , cmd_buf_dma );
717
762
out :
718
763
return efi_status ;
719
764
}
0 commit comments