Skip to content

Commit 0d423c4

Browse files
mRrvzsuperna9999
authored andcommitted
drivers: meson: sm: correct meson_sm_* API retval handling
1. Following the ARM SMC32 calling convention, the return value from secure monitor is a 32-bit signed integer. This patch changes the type of the return value of the function meson_sm_call(). 2. Now, when meson_sm_call() returns a 32-bit signed integer, we need to ensure that this value is not negative. It is important to check that the return value is not negative in both the meson_sm_call_read() and meson_sm_call_write() functions. 3. Add a comment explaining why it is necessary to check if the SMC return value is equal to 0 in the function meson_sm_call_read(). It is not obvious when reading this code. Signed-off-by: Alexey Romanov <avromanov@salutedevices.com> Reviewed-by: Neil Armstrong <neil.armstrong@linaro.org> Link: https://lore.kernel.org/r/20230830140850.17130-1-avromanov@salutedevices.com Signed-off-by: Neil Armstrong <neil.armstrong@linaro.org>
1 parent 0bb80ec commit 0d423c4

2 files changed

Lines changed: 14 additions & 8 deletions

File tree

drivers/firmware/meson/meson_sm.c

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ static u32 meson_sm_get_cmd(const struct meson_sm_chip *chip,
6767
return cmd->smc_id;
6868
}
6969

70-
static u32 __meson_sm_call(u32 cmd, u32 arg0, u32 arg1, u32 arg2,
70+
static s32 __meson_sm_call(u32 cmd, u32 arg0, u32 arg1, u32 arg2,
7171
u32 arg3, u32 arg4)
7272
{
7373
struct arm_smccc_res res;
@@ -102,9 +102,10 @@ static void __iomem *meson_sm_map_shmem(u32 cmd_shmem, unsigned int size)
102102
* Return: 0 on success, a negative value on error
103103
*/
104104
int meson_sm_call(struct meson_sm_firmware *fw, unsigned int cmd_index,
105-
u32 *ret, u32 arg0, u32 arg1, u32 arg2, u32 arg3, u32 arg4)
105+
s32 *ret, u32 arg0, u32 arg1, u32 arg2, u32 arg3, u32 arg4)
106106
{
107-
u32 cmd, lret;
107+
u32 cmd;
108+
s32 lret;
108109

109110
if (!fw->chip)
110111
return -ENOENT;
@@ -143,7 +144,7 @@ int meson_sm_call_read(struct meson_sm_firmware *fw, void *buffer,
143144
unsigned int bsize, unsigned int cmd_index, u32 arg0,
144145
u32 arg1, u32 arg2, u32 arg3, u32 arg4)
145146
{
146-
u32 size;
147+
s32 size;
147148
int ret;
148149

149150
if (!fw->chip)
@@ -158,11 +159,16 @@ int meson_sm_call_read(struct meson_sm_firmware *fw, void *buffer,
158159
if (meson_sm_call(fw, cmd_index, &size, arg0, arg1, arg2, arg3, arg4) < 0)
159160
return -EINVAL;
160161

161-
if (size > bsize)
162+
if (size < 0 || size > bsize)
162163
return -EINVAL;
163164

164165
ret = size;
165166

167+
/* In some cases (for example GET_CHIP_ID command),
168+
* SMC doesn't return the number of bytes read, even
169+
* though the bytes were actually read into sm_shmem_out.
170+
* So this check is needed.
171+
*/
166172
if (!size)
167173
size = bsize;
168174

@@ -192,7 +198,7 @@ int meson_sm_call_write(struct meson_sm_firmware *fw, void *buffer,
192198
unsigned int size, unsigned int cmd_index, u32 arg0,
193199
u32 arg1, u32 arg2, u32 arg3, u32 arg4)
194200
{
195-
u32 written;
201+
s32 written;
196202

197203
if (!fw->chip)
198204
return -ENOENT;
@@ -208,7 +214,7 @@ int meson_sm_call_write(struct meson_sm_firmware *fw, void *buffer,
208214
if (meson_sm_call(fw, cmd_index, &written, arg0, arg1, arg2, arg3, arg4) < 0)
209215
return -EINVAL;
210216

211-
if (!written)
217+
if (written <= 0 || written > size)
212218
return -EINVAL;
213219

214220
return written;

include/linux/firmware/meson/meson_sm.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ enum {
1919
struct meson_sm_firmware;
2020

2121
int meson_sm_call(struct meson_sm_firmware *fw, unsigned int cmd_index,
22-
u32 *ret, u32 arg0, u32 arg1, u32 arg2, u32 arg3, u32 arg4);
22+
s32 *ret, u32 arg0, u32 arg1, u32 arg2, u32 arg3, u32 arg4);
2323
int meson_sm_call_write(struct meson_sm_firmware *fw, void *buffer,
2424
unsigned int b_size, unsigned int cmd_index, u32 arg0,
2525
u32 arg1, u32 arg2, u32 arg3, u32 arg4);

0 commit comments

Comments
 (0)