TianoCore EDK2 master
Loading...
Searching...
No Matches
DxeTimerLib.c
Go to the documentation of this file.
1
9#include <PiPei.h>
10#include <Library/BaseLib.h>
11#include <Library/TimerLib.h>
12#include <Library/DebugLib.h>
13#include <Library/EmuThunkLib.h>
15#include <Library/UefiLib.h>
16
17#include <Protocol/Timer.h>
18
19STATIC UINT64 gTimerPeriod = 0;
21STATIC EFI_EVENT gTimerEvent = NULL;
22STATIC VOID *gRegistration = NULL;
23
24VOID
25EFIAPI
26RegisterTimerArchProtocol (
27 IN EFI_EVENT Event,
28 IN VOID *Context
29 )
30{
31 EFI_STATUS Status;
32
33 Status = gBS->LocateProtocol (&gEfiTimerArchProtocolGuid, NULL, (VOID **)&gTimerAp);
34 if (!EFI_ERROR (Status)) {
35 Status = gTimerAp->GetTimerPeriod (gTimerAp, &gTimerPeriod);
36 ASSERT_EFI_ERROR (Status);
37
38 // Convert to Nanoseconds.
39 gTimerPeriod = MultU64x32 (gTimerPeriod, 100);
40
41 if (gTimerEvent == NULL) {
42 Status = gBS->CreateEvent (EVT_TIMER, 0, NULL, NULL, &gTimerEvent);
43 ASSERT_EFI_ERROR (Status);
44 }
45 }
46}
47
59EFIAPI
61 IN UINTN MicroSeconds
62 )
63{
64 return NanoSecondDelay (MicroSeconds * 1000);
65}
66
78EFIAPI
80 IN UINTN NanoSeconds
81 )
82{
83 EFI_STATUS Status;
84 UINT64 HundredNanoseconds;
85 UINTN Index;
86
87 if ((gTimerPeriod != 0) &&
88 ((UINT64)NanoSeconds > gTimerPeriod) &&
89 (EfiGetCurrentTpl () == TPL_APPLICATION))
90 {
91 //
92 // This stall is long, so use gBS->WaitForEvent () to yield CPU to DXE Core
93 //
94
95 HundredNanoseconds = DivU64x32 (NanoSeconds, 100);
96 Status = gBS->SetTimer (gTimerEvent, TimerRelative, HundredNanoseconds);
97 ASSERT_EFI_ERROR (Status);
98
99 Status = gBS->WaitForEvent (sizeof (gTimerEvent)/sizeof (EFI_EVENT), &gTimerEvent, &Index);
100 ASSERT_EFI_ERROR (Status);
101 } else {
102 gEmuThunk->Sleep (NanoSeconds);
103 }
104
105 return NanoSeconds;
106}
107
119UINT64
120EFIAPI
122 VOID
123 )
124{
125 return gEmuThunk->QueryPerformanceCounter ();
126}
127
151UINT64
152EFIAPI
154 OUT UINT64 *StartValue OPTIONAL,
155 OUT UINT64 *EndValue OPTIONAL
156 )
157{
158 if (StartValue != NULL) {
159 *StartValue = 0ULL;
160 }
161
162 if (EndValue != NULL) {
163 *EndValue = (UINT64)-1LL;
164 }
165
166 return gEmuThunk->QueryPerformanceFrequency ();
167}
168
179EFIAPI
181 IN EFI_HANDLE ImageHandle,
182 IN EFI_SYSTEM_TABLE *SystemTable
183 )
184{
186 &gEfiTimerArchProtocolGuid,
187 TPL_CALLBACK,
188 RegisterTimerArchProtocol,
189 NULL,
190 &gRegistration
191 );
192
193 return EFI_SUCCESS;
194}
195
207UINT64
208EFIAPI
210 IN UINT64 Ticks
211 )
212{
213 UINT64 Frequency;
214 UINT64 NanoSeconds;
215 UINT64 Remainder;
216 INTN Shift;
217
219
220 //
221 // Ticks
222 // Time = --------- x 1,000,000,000
223 // Frequency
224 //
225 NanoSeconds = MultU64x32 (DivU64x64Remainder (Ticks, Frequency, &Remainder), 1000000000u);
226
227 //
228 // Ensure (Remainder * 1,000,000,000) will not overflow 64-bit.
229 // Since 2^29 < 1,000,000,000 = 0x3B9ACA00 < 2^30, Remainder should < 2^(64-30) = 2^34,
230 // i.e. highest bit set in Remainder should <= 33.
231 //
232 Shift = MAX (0, HighBitSet64 (Remainder) - 33);
233 Remainder = RShiftU64 (Remainder, (UINTN)Shift);
234 Frequency = RShiftU64 (Frequency, (UINTN)Shift);
235 NanoSeconds += DivU64x64Remainder (MultU64x32 (Remainder, 1000000000u), Frequency, NULL);
236
237 return NanoSeconds;
238}
UINT64 UINTN
INT64 INTN
UINT64 EFIAPI DivU64x32(IN UINT64 Dividend, IN UINT32 Divisor)
Definition: DivU64x32.c:29
UINT64 EFIAPI RShiftU64(IN UINT64 Operand, IN UINTN Count)
Definition: RShiftU64.c:28
UINT64 EFIAPI MultU64x32(IN UINT64 Multiplicand, IN UINT32 Multiplier)
Definition: MultU64x32.c:27
UINT64 EFIAPI DivU64x64Remainder(IN UINT64 Dividend, IN UINT64 Divisor, OUT UINT64 *Remainder OPTIONAL)
INTN EFIAPI HighBitSet64(IN UINT64 Operand)
Definition: HighBitSet64.c:27
UINT64 EFIAPI GetPerformanceCounterProperties(OUT UINT64 *StartValue OPTIONAL, OUT UINT64 *EndValue OPTIONAL)
Definition: DxeTimerLib.c:153
UINT64 EFIAPI GetTimeInNanoSecond(IN UINT64 Ticks)
Definition: DxeTimerLib.c:209
EFI_STATUS EFIAPI DxeTimerLibConstructor(IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable)
Definition: DxeTimerLib.c:180
UINT64 EFIAPI GetPerformanceCounter(VOID)
Definition: DxeTimerLib.c:121
UINTN EFIAPI MicroSecondDelay(IN UINTN MicroSeconds)
Definition: DxeTimerLib.c:60
UINTN EFIAPI NanoSecondDelay(IN UINTN NanoSeconds)
Definition: DxeTimerLib.c:79
#define NULL
Definition: Base.h:319
#define STATIC
Definition: Base.h:264
#define IN
Definition: Base.h:279
#define OUT
Definition: Base.h:284
#define MAX(a, b)
Definition: Base.h:992
#define ASSERT_EFI_ERROR(StatusParameter)
Definition: DebugLib.h:462
RETURN_STATUS EFI_STATUS
Definition: UefiBaseType.h:29
VOID * EFI_EVENT
Definition: UefiBaseType.h:37
VOID * EFI_HANDLE
Definition: UefiBaseType.h:33
#define EFI_SUCCESS
Definition: UefiBaseType.h:112
EFI_BOOT_SERVICES * gBS
EFI_TPL EFIAPI EfiGetCurrentTpl(VOID)
Definition: UefiLib.c:375
EFI_EVENT EFIAPI EfiCreateProtocolNotifyEvent(IN EFI_GUID *ProtocolGuid, IN EFI_TPL NotifyTpl, IN EFI_EVENT_NOTIFY NotifyFunction, IN VOID *NotifyContext OPTIONAL, OUT VOID **Registration)
Definition: UefiLib.c:134
@ TimerRelative
Definition: UefiSpec.h:539