mirror of https://github.com/acidanthera/audk.git
MdeModulePkg DXE Core: Fix overflow and truncation issues in the implementation of the Stall() boot service to follow the UEFI spec.
Signed-off-by: rsun3 Reviewed-by: mdkinney git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@12822 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
parent
49cc8d2215
commit
a62da87e95
|
@ -1,7 +1,7 @@
|
||||||
/** @file
|
/** @file
|
||||||
UEFI Miscellaneous boot Services Stall service implementation
|
UEFI Miscellaneous boot Services Stall service implementation
|
||||||
|
|
||||||
Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.<BR>
|
Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>
|
||||||
This program and the accompanying materials
|
This program and the accompanying materials
|
||||||
are licensed and made available under the terms and conditions of the BSD License
|
are licensed and made available under the terms and conditions of the BSD License
|
||||||
which accompanies this distribution. The full text of the license may be found at
|
which accompanies this distribution. The full text of the license may be found at
|
||||||
|
@ -18,7 +18,26 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||||
|
|
||||||
#include "DxeMain.h"
|
#include "DxeMain.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
Internal worker function to call the Metronome Architectural Protocol for
|
||||||
|
the number of ticks specified by the UINT64 Counter value. WaitForTick()
|
||||||
|
service of the Metronome Architectural Protocol uses a UINT32 for the number
|
||||||
|
of ticks to wait, so this function loops when Counter is larger than 0xffffffff.
|
||||||
|
|
||||||
|
@param Counter Number of ticks to wait.
|
||||||
|
|
||||||
|
**/
|
||||||
|
VOID
|
||||||
|
CoreInternalWaitForTick (
|
||||||
|
IN UINT64 Counter
|
||||||
|
)
|
||||||
|
{
|
||||||
|
while (Counter > 0xffffffff) {
|
||||||
|
gMetronome->WaitForTick (gMetronome, 0xffffffff);
|
||||||
|
Counter -= 0xffffffff;
|
||||||
|
}
|
||||||
|
gMetronome->WaitForTick (gMetronome, (UINT32)Counter);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Introduces a fine-grained stall.
|
Introduces a fine-grained stall.
|
||||||
|
@ -36,33 +55,59 @@ CoreStall (
|
||||||
IN UINTN Microseconds
|
IN UINTN Microseconds
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
UINT32 Counter;
|
UINT64 Counter;
|
||||||
UINT32 Remainder;
|
UINT32 Remainder;
|
||||||
|
UINTN Index;
|
||||||
|
|
||||||
if (gMetronome == NULL) {
|
if (gMetronome == NULL) {
|
||||||
return EFI_NOT_AVAILABLE_YET;
|
return EFI_NOT_AVAILABLE_YET;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Calculate the number of ticks by dividing the number of microseconds by
|
// Counter = Microseconds * 10 / gMetronome->TickPeriod
|
||||||
// the TickPeriod.
|
// 0x1999999999999999 = (2^64 - 1) / 10
|
||||||
// Calculation is based on 100ns unit.
|
|
||||||
//
|
//
|
||||||
Counter = (UINT32) DivU64x32Remainder (
|
if (Microseconds > 0x1999999999999999ULL) {
|
||||||
Microseconds * 10,
|
//
|
||||||
gMetronome->TickPeriod,
|
// Microseconds is too large to multiple by 10 first. Perform the divide
|
||||||
&Remainder
|
// operation first and loop 10 times to avoid 64-bit math overflow.
|
||||||
);
|
//
|
||||||
|
Counter = DivU64x32Remainder (
|
||||||
|
Microseconds,
|
||||||
|
gMetronome->TickPeriod,
|
||||||
|
&Remainder
|
||||||
|
);
|
||||||
|
for (Index = 0; Index < 10; Index++) {
|
||||||
|
CoreInternalWaitForTick (Counter);
|
||||||
|
}
|
||||||
|
|
||||||
//
|
if (Remainder != 0) {
|
||||||
// Call WaitForTick for Counter + 1 ticks to try to guarantee Counter tick
|
//
|
||||||
// periods, thus attempting to ensure Microseconds of stall time.
|
// If Remainder was not zero, then normally, Counter would be rounded
|
||||||
//
|
// up by 1 tick. In this case, since a loop for 10 counts was used
|
||||||
if (Remainder != 0) {
|
// to emulate the multiply by 10 operation, Counter needs to be rounded
|
||||||
Counter++;
|
// up by 10 counts.
|
||||||
|
//
|
||||||
|
CoreInternalWaitForTick (10);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
//
|
||||||
|
// Calculate the number of ticks by dividing the number of microseconds by
|
||||||
|
// the TickPeriod. Calculation is based on 100ns unit.
|
||||||
|
//
|
||||||
|
Counter = DivU64x32Remainder (
|
||||||
|
MultU64x32 (Microseconds, 10),
|
||||||
|
gMetronome->TickPeriod,
|
||||||
|
&Remainder
|
||||||
|
);
|
||||||
|
if (Remainder != 0) {
|
||||||
|
//
|
||||||
|
// If Remainder is not zero, then round Counter up by one tick.
|
||||||
|
//
|
||||||
|
Counter++;
|
||||||
|
}
|
||||||
|
CoreInternalWaitForTick (Counter);
|
||||||
}
|
}
|
||||||
|
|
||||||
gMetronome->WaitForTick (gMetronome, Counter);
|
|
||||||
|
|
||||||
return EFI_SUCCESS;
|
return EFI_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue