From 83e007a0c6a3f4bfdf8f3f8d0fc266cda189b3d6 Mon Sep 17 00:00:00 2001
From: Carlo Caione <carlo@endlessm.com>
Date: Fri, 3 Mar 2017 16:17:58 +0100
Subject: firmware: meson-sm: Check for buffer output size

After the data is read by the secure monitor driver it is being copied
in the output buffer checking only the size of the bounce buffer but not
the size of the output buffer.

Fix this in the secure monitor driver slightly changing the API. Fix
also the efuse driver that it is the only driver using this API to not
break bisectability.

Signed-off-by: Carlo Caione <carlo@endlessm.com>
Acked-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org> # for nvmem
Acked-by: Mark Rutland <mark.rutland@arm.com>
Signed-off-by: Kevin Hilman <khilman@baylibre.com>
---
 drivers/firmware/meson/meson_sm.c | 10 +++++++---
 1 file changed, 7 insertions(+), 3 deletions(-)

(limited to 'drivers/firmware')

diff --git a/drivers/firmware/meson/meson_sm.c b/drivers/firmware/meson/meson_sm.c
index b0d2549..5f30a57 100644
--- a/drivers/firmware/meson/meson_sm.c
+++ b/drivers/firmware/meson/meson_sm.c
@@ -127,6 +127,7 @@ EXPORT_SYMBOL(meson_sm_call);
  * meson_sm_call_read - retrieve data from secure-monitor
  *
  * @buffer:	Buffer to store the retrieved data
+ * @bsize:	Size of the buffer
  * @cmd_index:	Index of the SMC32 function ID
  * @arg0:	SMC32 Argument 0
  * @arg1:	SMC32 Argument 1
@@ -136,8 +137,8 @@ EXPORT_SYMBOL(meson_sm_call);
  *
  * Return:	size of read data on success, a negative value on error
  */
-int meson_sm_call_read(void *buffer, unsigned int cmd_index, u32 arg0,
-		       u32 arg1, u32 arg2, u32 arg3, u32 arg4)
+int meson_sm_call_read(void *buffer, unsigned int bsize, unsigned int cmd_index,
+		       u32 arg0, u32 arg1, u32 arg2, u32 arg3, u32 arg4)
 {
 	u32 size;
 
@@ -147,10 +148,13 @@ int meson_sm_call_read(void *buffer, unsigned int cmd_index, u32 arg0,
 	if (!fw.chip->cmd_shmem_out_base)
 		return -EINVAL;
 
+	if (bsize > fw.chip->shmem_size)
+		return -EINVAL;
+
 	if (meson_sm_call(cmd_index, &size, arg0, arg1, arg2, arg3, arg4) < 0)
 		return -EINVAL;
 
-	if (!size || size > fw.chip->shmem_size)
+	if (!size || size > bsize)
 		return -EINVAL;
 
 	if (buffer)
-- 
cgit v1.1


From 7a9bc330df9b8fb3245d50a198b5c6d4d634b06f Mon Sep 17 00:00:00 2001
From: Carlo Caione <carlo@endlessm.com>
Date: Fri, 3 Mar 2017 16:17:59 +0100
Subject: firmware: meson-sm: Allow 0 as valid return value

Some special SMC calls (i.e. the function used to retrieve the serial
number of the Amlogic SoCs) returns 0 in the register 0 also when the
data was successfully read instead of using the register to hold the
number of bytes returned in the bounce buffer as expected.

With the current implementation of the driver this is seen as an error
and meson_sm_call_read() returns an error even though the data was
correctly read.

To deal with this when we have no information about the amount of read
data (that is 0 is returned by the SMC call) we return to the caller
the requested amount of data and 0 as return value.

Signed-off-by: Carlo Caione <carlo@endlessm.com>
Acked-by: Mark Rutland <mark.rutland@arm.com>
Signed-off-by: Kevin Hilman <khilman@baylibre.com>
---
 drivers/firmware/meson/meson_sm.c | 12 ++++++++++--
 1 file changed, 10 insertions(+), 2 deletions(-)

(limited to 'drivers/firmware')

diff --git a/drivers/firmware/meson/meson_sm.c b/drivers/firmware/meson/meson_sm.c
index 5f30a57..ff20442 100644
--- a/drivers/firmware/meson/meson_sm.c
+++ b/drivers/firmware/meson/meson_sm.c
@@ -136,11 +136,14 @@ EXPORT_SYMBOL(meson_sm_call);
  * @arg4:	SMC32 Argument 4
  *
  * Return:	size of read data on success, a negative value on error
+ *		When 0 is returned there is no guarantee about the amount of
+ *		data read and bsize bytes are copied in buffer.
  */
 int meson_sm_call_read(void *buffer, unsigned int bsize, unsigned int cmd_index,
 		       u32 arg0, u32 arg1, u32 arg2, u32 arg3, u32 arg4)
 {
 	u32 size;
+	int ret;
 
 	if (!fw.chip)
 		return -ENOENT;
@@ -154,13 +157,18 @@ int meson_sm_call_read(void *buffer, unsigned int bsize, unsigned int cmd_index,
 	if (meson_sm_call(cmd_index, &size, arg0, arg1, arg2, arg3, arg4) < 0)
 		return -EINVAL;
 
-	if (!size || size > bsize)
+	if (size > bsize)
 		return -EINVAL;
 
+	ret = size;
+
+	if (!size)
+		size = bsize;
+
 	if (buffer)
 		memcpy(buffer, fw.sm_shmem_out_base, size);
 
-	return size;
+	return ret;
 }
 EXPORT_SYMBOL(meson_sm_call_read);
 
-- 
cgit v1.1