summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohnny.Fan <Johnny.Fan@cixtech.com>2025-04-15 10:33:55 +0800
committermergify[bot] <37929162+mergify[bot]@users.noreply.github.com>2025-04-22 09:23:32 +0000
commitf96d38f432b680b0b652842b98153fef13e56329 (patch)
tree5e6c9e402df89b8ba6f619e154df35fb4e66bb7f
parent8406e672e846e37dc292065f36d25242d961647b (diff)
downloadedk2-f96d38f432b680b0b652842b98153fef13e56329.zip
edk2-f96d38f432b680b0b652842b98153fef13e56329.tar.gz
edk2-f96d38f432b680b0b652842b98153fef13e56329.tar.bz2
ArmPkg/ArmScmiDxe: Fix SCMI param overwrite in multi-transaction scenario
Fix an issue where input parameters in SCMI messages may be overwritten by return values during repeated transactions when retrieving large data sets. This issue affects: 1. ClockDescribeRates: when the number of clock rates exceeds the transfer limit. According to the SCMI specification (Section 4.6.2.5), the first and second parameters are initially used to pass clock_id and rate_index. However, due to SCMI’s shared memory communication mechanism, these same memory locations are later reused to return status and num_rate_flags. 2. PerformanceDescribeLevels: when the number of performance levels is too large to return in a single response. As described in Section 4.5.3.5, the first and second parameters are initially used for domain_id and level_index, but are overwritten with status and num_levels in the return. Because SCMI reuses the same shared memory buffer for both input and output, the return values can override input parameters if the buffer is not properly re-initialized before each request. This patch ensures that the first and second parameters are correctly set before every transaction to preserve input integrity and ensure correct protocol behavior. Signed-off-by: jie.fu <jie.fu@cixtech.com>
-rw-r--r--ArmPkg/Drivers/ArmScmiDxe/ScmiClockProtocol.c10
-rw-r--r--ArmPkg/Drivers/ArmScmiDxe/ScmiPerformanceProtocol.c10
2 files changed, 12 insertions, 8 deletions
diff --git a/ArmPkg/Drivers/ArmScmiDxe/ScmiClockProtocol.c b/ArmPkg/Drivers/ArmScmiDxe/ScmiClockProtocol.c
index f092208..1b11d72 100644
--- a/ArmPkg/Drivers/ArmScmiDxe/ScmiClockProtocol.c
+++ b/ArmPkg/Drivers/ArmScmiDxe/ScmiClockProtocol.c
@@ -186,7 +186,8 @@ ClockDescribeRates (
UINT32 PayloadLength;
SCMI_COMMAND Cmd;
- UINT32 *MessageParams;
+ UINT32 *MessageParams1;
+ UINT32 *MessageParams2;
CLOCK_DESCRIBE_RATES *DescribeRates;
CLOCK_RATE_DWORD *Rate;
@@ -199,7 +200,7 @@ ClockDescribeRates (
RequiredArraySize = 0;
RateIndex = 0;
- Status = ScmiCommandGetPayload (&MessageParams);
+ Status = ScmiCommandGetPayload (&MessageParams1);
if (EFI_ERROR (Status)) {
return Status;
}
@@ -207,10 +208,11 @@ ClockDescribeRates (
Cmd.ProtocolId = ScmiProtocolIdClock;
Cmd.MessageId = ScmiMessageIdClockDescribeRates;
- *MessageParams++ = ClockId;
+ MessageParams2 = MessageParams1 + 1;
do {
- *MessageParams = RateIndex;
+ *MessageParams1 = ClockId;
+ *MessageParams2 = RateIndex;
// Set Payload length, note PayloadLength is a IN/OUT parameter.
PayloadLength = sizeof (ClockId) + sizeof (RateIndex);
diff --git a/ArmPkg/Drivers/ArmScmiDxe/ScmiPerformanceProtocol.c b/ArmPkg/Drivers/ArmScmiDxe/ScmiPerformanceProtocol.c
index 91efce4..12aa458 100644
--- a/ArmPkg/Drivers/ArmScmiDxe/ScmiPerformanceProtocol.c
+++ b/ArmPkg/Drivers/ArmScmiDxe/ScmiPerformanceProtocol.c
@@ -160,7 +160,8 @@ PerformanceDescribeLevels (
EFI_STATUS Status;
UINT32 PayloadLength;
SCMI_COMMAND Cmd;
- UINT32 *MessageParams;
+ UINT32 *MessageParams1;
+ UINT32 *MessageParams2;
UINT32 LevelIndex;
UINT32 RequiredSize;
UINT32 LevelNo;
@@ -169,7 +170,7 @@ PerformanceDescribeLevels (
PERF_DESCRIBE_LEVELS *Levels;
- Status = ScmiCommandGetPayload (&MessageParams);
+ Status = ScmiCommandGetPayload (&MessageParams1);
if (EFI_ERROR (Status)) {
return Status;
}
@@ -177,13 +178,14 @@ PerformanceDescribeLevels (
LevelIndex = 0;
RequiredSize = 0;
- *MessageParams++ = DomainId;
+ MessageParams2 = MessageParams1 + 1;
Cmd.ProtocolId = ScmiProtocolIdPerformance;
Cmd.MessageId = ScmiMessageIdPerformanceDescribeLevels;
do {
- *MessageParams = LevelIndex;
+ *MessageParams1 = DomainId;
+ *MessageParams2 = LevelIndex;
// Note, PayloadLength is an IN/OUT parameter.
PayloadLength = sizeof (DomainId) + sizeof (LevelIndex);