@@ -221,6 +221,19 @@ struct qsee_rsp_uefi_query_variable_info {
221221 * alignment of 8 bytes (64 bits) for GUIDs. Our definition of efi_guid_t,
222222 * however, has an alignment of 4 byte (32 bits). So far, this seems to work
223223 * 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.
224237 */
225238#define qcuefi_buf_align_fields (fields ...) \
226239 ({ \
@@ -244,6 +257,12 @@ struct qsee_rsp_uefi_query_variable_info {
244257#define __array_offs (type , count , offset ) \
245258 __field_impl(sizeof(type) * (count), __alignof__(type), offset)
246259
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+
247266#define __array (type , count ) __array_offs(type, count, NULL)
248267#define __field_offs (type , offset ) __array_offs(type, 1, offset)
249268#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
277296 unsigned long buffer_size = * data_size ;
278297 efi_status_t efi_status = EFI_SUCCESS ;
279298 unsigned long name_length ;
299+ dma_addr_t cmd_buf_dma ;
300+ size_t cmd_buf_size ;
301+ void * cmd_buf ;
280302 size_t guid_offs ;
281303 size_t name_offs ;
282304 size_t req_size ;
283305 size_t rsp_size ;
306+ size_t req_offs ;
307+ size_t rsp_offs ;
284308 ssize_t status ;
285309
286310 if (!name || !guid )
@@ -304,17 +328,19 @@ static efi_status_t qsee_uefi_get_variable(struct qcuefi_client *qcuefi, const e
304328 __array (u8 , buffer_size )
305329 );
306330
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 ) {
309338 efi_status = EFI_OUT_OF_RESOURCES ;
310339 goto out ;
311340 }
312341
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 ;
318344
319345 req_data -> command_id = QSEE_CMD_UEFI_GET_VARIABLE ;
320346 req_data -> data_size = buffer_size ;
@@ -332,7 +358,9 @@ static efi_status_t qsee_uefi_get_variable(struct qcuefi_client *qcuefi, const e
332358
333359 memcpy (((void * )req_data ) + req_data -> guid_offset , guid , req_data -> guid_size );
334360
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 );
336364 if (status ) {
337365 efi_status = EFI_DEVICE_ERROR ;
338366 goto out_free ;
@@ -407,9 +435,7 @@ static efi_status_t qsee_uefi_get_variable(struct qcuefi_client *qcuefi, const e
407435 memcpy (data , ((void * )rsp_data ) + rsp_data -> data_offset , rsp_data -> data_size );
408436
409437out_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 );
413439out :
414440 return efi_status ;
415441}
@@ -422,10 +448,15 @@ static efi_status_t qsee_uefi_set_variable(struct qcuefi_client *qcuefi, const e
422448 struct qsee_rsp_uefi_set_variable * rsp_data ;
423449 efi_status_t efi_status = EFI_SUCCESS ;
424450 unsigned long name_length ;
451+ dma_addr_t cmd_buf_dma ;
452+ size_t cmd_buf_size ;
453+ void * cmd_buf ;
425454 size_t name_offs ;
426455 size_t guid_offs ;
427456 size_t data_offs ;
428457 size_t req_size ;
458+ size_t req_offs ;
459+ size_t rsp_offs ;
429460 ssize_t status ;
430461
431462 if (!name || !guid )
@@ -450,17 +481,19 @@ static efi_status_t qsee_uefi_set_variable(struct qcuefi_client *qcuefi, const e
450481 __array_offs (u8 , data_size , & data_offs )
451482 );
452483
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 ) {
455491 efi_status = EFI_OUT_OF_RESOURCES ;
456492 goto out ;
457493 }
458494
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 ;
464497
465498 req_data -> command_id = QSEE_CMD_UEFI_SET_VARIABLE ;
466499 req_data -> attributes = attributes ;
@@ -483,8 +516,9 @@ static efi_status_t qsee_uefi_set_variable(struct qcuefi_client *qcuefi, const e
483516 if (data_size )
484517 memcpy (((void * )req_data ) + req_data -> data_offset , data , req_data -> data_size );
485518
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 ));
488522 if (status ) {
489523 efi_status = EFI_DEVICE_ERROR ;
490524 goto out_free ;
@@ -507,9 +541,7 @@ static efi_status_t qsee_uefi_set_variable(struct qcuefi_client *qcuefi, const e
507541 }
508542
509543out_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 );
513545out :
514546 return efi_status ;
515547}
@@ -521,10 +553,15 @@ static efi_status_t qsee_uefi_get_next_variable(struct qcuefi_client *qcuefi,
521553 struct qsee_req_uefi_get_next_variable * req_data ;
522554 struct qsee_rsp_uefi_get_next_variable * rsp_data ;
523555 efi_status_t efi_status = EFI_SUCCESS ;
556+ dma_addr_t cmd_buf_dma ;
557+ size_t cmd_buf_size ;
558+ void * cmd_buf ;
524559 size_t guid_offs ;
525560 size_t name_offs ;
526561 size_t req_size ;
527562 size_t rsp_size ;
563+ size_t req_offs ;
564+ size_t rsp_offs ;
528565 ssize_t status ;
529566
530567 if (!name_size || !name || !guid )
@@ -545,17 +582,19 @@ static efi_status_t qsee_uefi_get_next_variable(struct qcuefi_client *qcuefi,
545582 __array (* name , * name_size / sizeof (* name ))
546583 );
547584
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 ) {
550592 efi_status = EFI_OUT_OF_RESOURCES ;
551593 goto out ;
552594 }
553595
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 ;
559598
560599 req_data -> command_id = QSEE_CMD_UEFI_GET_NEXT_VARIABLE ;
561600 req_data -> guid_offset = guid_offs ;
@@ -572,7 +611,9 @@ static efi_status_t qsee_uefi_get_next_variable(struct qcuefi_client *qcuefi,
572611 goto out_free ;
573612 }
574613
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 );
576617 if (status ) {
577618 efi_status = EFI_DEVICE_ERROR ;
578619 goto out_free ;
@@ -645,9 +686,7 @@ static efi_status_t qsee_uefi_get_next_variable(struct qcuefi_client *qcuefi,
645686 }
646687
647688out_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 );
651690out :
652691 return efi_status ;
653692}
@@ -659,26 +698,34 @@ static efi_status_t qsee_uefi_query_variable_info(struct qcuefi_client *qcuefi,
659698 struct qsee_req_uefi_query_variable_info * req_data ;
660699 struct qsee_rsp_uefi_query_variable_info * rsp_data ;
661700 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 ;
662706 int status ;
663707
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 ) {
666715 efi_status = EFI_OUT_OF_RESOURCES ;
667716 goto out ;
668717 }
669718
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 ;
675721
676722 req_data -> command_id = QSEE_CMD_UEFI_QUERY_VARIABLE_INFO ;
677723 req_data -> attributes = attr ;
678724 req_data -> length = sizeof (* req_data );
679725
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 ));
682729 if (status ) {
683730 efi_status = EFI_DEVICE_ERROR ;
684731 goto out_free ;
@@ -711,9 +758,7 @@ static efi_status_t qsee_uefi_query_variable_info(struct qcuefi_client *qcuefi,
711758 * max_variable_size = rsp_data -> max_variable_size ;
712759
713760out_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 );
717762out :
718763 return efi_status ;
719764}
0 commit comments