summaryrefslogtreecommitdiffstats
path: root/UefiCpuPkg
diff options
context:
space:
mode:
authorEric Dong <eric.dong@intel.com>2017-08-21 14:40:44 +0800
committerEric Dong <eric.dong@intel.com>2017-08-28 15:13:48 +0800
commit48cfb7c0f4a8ed01ce4883029724d4eb2724b48a (patch)
tree067dc58fa231cf395085ebbdc955055a785f2792 /UefiCpuPkg
parent714c2603018a99a514c42c2b511c821f30ba9cdf (diff)
downloadedk2-48cfb7c0f4a8ed01ce4883029724d4eb2724b48a.tar.gz
edk2-48cfb7c0f4a8ed01ce4883029724d4eb2724b48a.tar.bz2
edk2-48cfb7c0f4a8ed01ce4883029724d4eb2724b48a.zip
UefiCpuPkg/MpLib: fix potential overflow issue.
Current calculate timeout logic may have overflow if the input timeout value too large. This patch fix this potential overflow issue. V2: Use local variable instead of call GetPerformanceCounterProperties twice. Also correct some comments. Cc: Michael Kinney <michael.d.kinney@intel.com> Cc: Ruiyu Ni <ruiyu.ni@intel.com> Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Eric Dong <eric.dong@intel.com> Reviewed-by: Michael Kinney <michael.d.kinney@intel.com>
Diffstat (limited to 'UefiCpuPkg')
-rw-r--r--UefiCpuPkg/Library/MpInitLib/MpLib.c43
1 files changed, 33 insertions, 10 deletions
diff --git a/UefiCpuPkg/Library/MpInitLib/MpLib.c b/UefiCpuPkg/Library/MpInitLib/MpLib.c
index ed1f55e955..8394572c61 100644
--- a/UefiCpuPkg/Library/MpInitLib/MpLib.c
+++ b/UefiCpuPkg/Library/MpInitLib/MpLib.c
@@ -1001,6 +1001,9 @@ CalculateTimeout (
OUT UINT64 *CurrentTime
)
{
+ UINT64 TimeoutInSeconds;
+ UINT64 TimestampCounterFreq;
+
//
// Read the current value of the performance counter
//
@@ -1016,16 +1019,36 @@ CalculateTimeout (
//
// GetPerformanceCounterProperties () returns the timestamp counter's frequency
- // in Hz. So multiply the return value with TimeoutInMicroseconds and then divide
- // it by 1,000,000, to get the number of ticks for the timeout value.
- //
- return DivU64x32 (
- MultU64x64 (
- GetPerformanceCounterProperties (NULL, NULL),
- TimeoutInMicroseconds
- ),
- 1000000
- );
+ // in Hz.
+ //
+ TimestampCounterFreq = GetPerformanceCounterProperties (NULL, NULL);
+
+ //
+ // Check the potential overflow before calculate the number of ticks for the timeout value.
+ //
+ if (DivU64x64Remainder (MAX_UINT64, TimeoutInMicroseconds, NULL) < TimestampCounterFreq) {
+ //
+ // Convert microseconds into seconds if direct multiplication overflows
+ //
+ TimeoutInSeconds = DivU64x32 (TimeoutInMicroseconds, 1000000);
+ //
+ // Assertion if the final tick count exceeds MAX_UINT64
+ //
+ ASSERT (DivU64x64Remainder (MAX_UINT64, TimeoutInSeconds, NULL) >= TimestampCounterFreq);
+ return MultU64x64 (TimestampCounterFreq, TimeoutInSeconds);
+ } else {
+ //
+ // No overflow case, multiply the return value with TimeoutInMicroseconds and then divide
+ // it by 1,000,000, to get the number of ticks for the timeout value.
+ //
+ return DivU64x32 (
+ MultU64x64 (
+ TimestampCounterFreq,
+ TimeoutInMicroseconds
+ ),
+ 1000000
+ );
+ }
}
/**