| From eb71f8a5e33fa1066fb92f0111ab366a341e1f6c Mon Sep 17 00:00:00 2001 |
| From: honclo <honclo@imap.linux.ibm.com> |
| Date: Thu, 12 Feb 2015 21:02:24 -0500 |
| Subject: Added Little Endian support to vtpm module |
| |
| From: honclo <honclo@imap.linux.ibm.com> |
| |
| commit eb71f8a5e33fa1066fb92f0111ab366a341e1f6c upstream. |
| |
| The tpm_ibmvtpm module is affected by an unaligned access problem. |
| ibmvtpm_crq_get_version failed with rc=-4 during boot when vTPM is |
| enabled in Power partition, which supports both little endian and |
| big endian modes. |
| |
| We added little endian support to fix this problem: |
| 1) added cpu_to_be64 calls to ensure BE data is sent from an LE OS. |
| 2) added be16_to_cpu and be32_to_cpu calls to make sure data received |
| is in LE format on a LE OS. |
| |
| Signed-off-by: Hon Ching(Vicky) Lo <honclo@linux.vnet.ibm.com> |
| Signed-off-by: Joy Latten <jmlatten@linux.vnet.ibm.com> |
| [phuewe: manually applied the patch :( ] |
| Reviewed-by: Ashley Lai <ashley@ahsleylai.com> |
| Signed-off-by: Peter Huewe <peterhuewe@gmx.de> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| drivers/char/tpm/tpm_ibmvtpm.c | 20 ++++++++++++-------- |
| 1 file changed, 12 insertions(+), 8 deletions(-) |
| |
| --- a/drivers/char/tpm/tpm_ibmvtpm.c |
| +++ b/drivers/char/tpm/tpm_ibmvtpm.c |
| @@ -148,7 +148,8 @@ static int tpm_ibmvtpm_send(struct tpm_c |
| crq.len = (u16)count; |
| crq.data = ibmvtpm->rtce_dma_handle; |
| |
| - rc = ibmvtpm_send_crq(ibmvtpm->vdev, word[0], word[1]); |
| + rc = ibmvtpm_send_crq(ibmvtpm->vdev, cpu_to_be64(word[0]), |
| + cpu_to_be64(word[1])); |
| if (rc != H_SUCCESS) { |
| dev_err(ibmvtpm->dev, "tpm_ibmvtpm_send failed rc=%d\n", rc); |
| rc = 0; |
| @@ -186,7 +187,8 @@ static int ibmvtpm_crq_get_rtce_size(str |
| crq.valid = (u8)IBMVTPM_VALID_CMD; |
| crq.msg = (u8)VTPM_GET_RTCE_BUFFER_SIZE; |
| |
| - rc = ibmvtpm_send_crq(ibmvtpm->vdev, buf[0], buf[1]); |
| + rc = ibmvtpm_send_crq(ibmvtpm->vdev, cpu_to_be64(buf[0]), |
| + cpu_to_be64(buf[1])); |
| if (rc != H_SUCCESS) |
| dev_err(ibmvtpm->dev, |
| "ibmvtpm_crq_get_rtce_size failed rc=%d\n", rc); |
| @@ -212,7 +214,8 @@ static int ibmvtpm_crq_get_version(struc |
| crq.valid = (u8)IBMVTPM_VALID_CMD; |
| crq.msg = (u8)VTPM_GET_VERSION; |
| |
| - rc = ibmvtpm_send_crq(ibmvtpm->vdev, buf[0], buf[1]); |
| + rc = ibmvtpm_send_crq(ibmvtpm->vdev, cpu_to_be64(buf[0]), |
| + cpu_to_be64(buf[1])); |
| if (rc != H_SUCCESS) |
| dev_err(ibmvtpm->dev, |
| "ibmvtpm_crq_get_version failed rc=%d\n", rc); |
| @@ -335,7 +338,8 @@ static int tpm_ibmvtpm_suspend(struct de |
| crq.valid = (u8)IBMVTPM_VALID_CMD; |
| crq.msg = (u8)VTPM_PREPARE_TO_SUSPEND; |
| |
| - rc = ibmvtpm_send_crq(ibmvtpm->vdev, buf[0], buf[1]); |
| + rc = ibmvtpm_send_crq(ibmvtpm->vdev, cpu_to_be64(buf[0]), |
| + cpu_to_be64(buf[1])); |
| if (rc != H_SUCCESS) |
| dev_err(ibmvtpm->dev, |
| "tpm_ibmvtpm_suspend failed rc=%d\n", rc); |
| @@ -480,11 +484,11 @@ static void ibmvtpm_crq_process(struct i |
| case IBMVTPM_VALID_CMD: |
| switch (crq->msg) { |
| case VTPM_GET_RTCE_BUFFER_SIZE_RES: |
| - if (crq->len <= 0) { |
| + if (be16_to_cpu(crq->len) <= 0) { |
| dev_err(ibmvtpm->dev, "Invalid rtce size\n"); |
| return; |
| } |
| - ibmvtpm->rtce_size = crq->len; |
| + ibmvtpm->rtce_size = be16_to_cpu(crq->len); |
| ibmvtpm->rtce_buf = kmalloc(ibmvtpm->rtce_size, |
| GFP_KERNEL); |
| if (!ibmvtpm->rtce_buf) { |
| @@ -505,11 +509,11 @@ static void ibmvtpm_crq_process(struct i |
| |
| return; |
| case VTPM_GET_VERSION_RES: |
| - ibmvtpm->vtpm_version = crq->data; |
| + ibmvtpm->vtpm_version = be32_to_cpu(crq->data); |
| return; |
| case VTPM_TPM_COMMAND_RES: |
| /* len of the data in rtce buffer */ |
| - ibmvtpm->res_len = crq->len; |
| + ibmvtpm->res_len = be16_to_cpu(crq->len); |
| wake_up_interruptible(&ibmvtpm->wq); |
| return; |
| default: |