1 /** @file 2 Implementation of Timestamp Protocol using UEFI APIs. 3 4 Copyright (c) 2013, Intel Corporation. All rights reserved.<BR> 5 This program and the accompanying materials 6 are licensed and made available under the terms and conditions of the BSD License 7 which accompanies this distribution. The full text of the license may be found at 8 http://opensource.org/licenses/bsd-license.php 9 10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. 12 13 **/ 14 15 #include <Uefi.h> 16 #include <Library/DebugLib.h> 17 #include <Library/UefiDriverEntryPoint.h> 18 #include <Library/UefiBootServicesTableLib.h> 19 #include <Library/TimerLib.h> 20 #include <Library/BaseMemoryLib.h> 21 #include <Protocol/Timestamp.h> 22 23 // 24 // The StartValue in TimerLib 25 // 26 UINT64 mTimerLibStartValue = 0; 27 28 // 29 // The EndValue in TimerLib 30 // 31 UINT64 mTimerLibEndValue = 0; 32 33 // 34 // The properties of timestamp 35 // 36 EFI_TIMESTAMP_PROPERTIES mTimestampProperties = { 37 0, 38 0 39 }; 40 41 /** 42 Retrieves the current value of a 64-bit free running timestamp counter. 43 44 The counter shall count up in proportion to the amount of time that has passed. The counter value 45 will always roll over to zero. The properties of the counter can be retrieved from GetProperties(). 46 The caller should be prepared for the function to return the same value twice across successive calls. 47 The counter value will not go backwards other than when wrapping, as defined by EndValue in GetProperties(). 48 The frequency of the returned timestamp counter value must remain constant. Power management operations that 49 affect clocking must not change the returned counter frequency. The quantization of counter value updates may 50 vary as long as the value reflecting time passed remains consistent. 51 52 @retval The current value of the free running timestamp counter. 53 54 **/ 55 UINT64 56 EFIAPI 57 TimestampDriverGetTimestamp ( 58 VOID 59 ) 60 { 61 // 62 // The timestamp of Timestamp Protocol 63 // 64 UINT64 TimestampValue; 65 TimestampValue = 0; 66 67 // 68 // Get the timestamp 69 // 70 if (mTimerLibStartValue > mTimerLibEndValue) { 71 TimestampValue = mTimerLibStartValue - GetPerformanceCounter(); 72 } else { 73 TimestampValue = GetPerformanceCounter() - mTimerLibStartValue; 74 } 75 76 return TimestampValue; 77 } 78 79 /** 80 Obtains timestamp counter properties including frequency and value limits. 81 82 @param[out] Properties The properties of the timestamp counter. 83 84 @retval EFI_SUCCESS The properties were successfully retrieved. 85 @retval EFI_DEVICE_ERROR An error occurred trying to retrieve the properties of the timestamp 86 counter subsystem. Properties is not pedated. 87 @retval EFI_INVALID_PARAMETER Properties is NULL. 88 89 **/ 90 EFI_STATUS 91 EFIAPI 92 TimestampDriverGetProperties( 93 OUT EFI_TIMESTAMP_PROPERTIES *Properties 94 ) 95 { 96 if (Properties == NULL) { 97 return EFI_INVALID_PARAMETER; 98 } 99 100 // 101 // Get timestamp properties 102 // 103 CopyMem((VOID *) Properties, (VOID *) &mTimestampProperties, sizeof (mTimestampProperties)); 104 105 return EFI_SUCCESS; 106 } 107 108 // 109 // The Timestamp Protocol instance produced by this driver 110 // 111 EFI_TIMESTAMP_PROTOCOL mTimestamp = { 112 TimestampDriverGetTimestamp, 113 TimestampDriverGetProperties 114 }; 115 116 /** 117 Entry point of the Timestamp Protocol driver. 118 119 @param ImageHandle The image handle of this driver. 120 @param SystemTable The pointer of EFI_SYSTEM_TABLE. 121 122 @retval EFI_SUCCESS Watchdog Timer Architectural Protocol successfully installed. 123 124 **/ 125 EFI_STATUS 126 EFIAPI 127 TimestampDriverInitialize ( 128 IN EFI_HANDLE ImageHandle, 129 IN EFI_SYSTEM_TABLE *SystemTable 130 ) 131 { 132 EFI_STATUS Status; 133 134 EFI_HANDLE TimestampHandle; 135 TimestampHandle = NULL; 136 137 // 138 // Get the start value, end value and frequency in Timerlib 139 // 140 mTimestampProperties.Frequency = GetPerformanceCounterProperties(&mTimerLibStartValue, &mTimerLibEndValue); 141 142 // 143 // Set the EndValue 144 // 145 if (mTimerLibEndValue > mTimerLibStartValue) { 146 mTimestampProperties.EndValue = mTimerLibEndValue - mTimerLibStartValue; 147 } else { 148 mTimestampProperties.EndValue = mTimerLibStartValue - mTimerLibEndValue; 149 } 150 151 DEBUG ((EFI_D_INFO, "TimerFrequency:0x%lx, TimerLibStartTime:0x%lx, TimerLibEndtime:0x%lx\n", mTimestampProperties.Frequency, mTimerLibStartValue, mTimerLibEndValue)); 152 153 // 154 // Install the Timestamp Protocol onto a new handle 155 // 156 Status = gBS->InstallMultipleProtocolInterfaces ( 157 &TimestampHandle, 158 &gEfiTimestampProtocolGuid, 159 &mTimestamp, 160 NULL 161 ); 162 163 ASSERT_EFI_ERROR (Status); 164 165 return EFI_SUCCESS; 166 } 167