timer.c 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287
  1. /*++
  2. Copyright (c) 2014 Minoca Corp.
  3. This file is licensed under the terms of the GNU General Public License
  4. version 3. Alternative licensing terms are available. Contact
  5. info@minocacorp.com for details. See the LICENSE file at the root of this
  6. project for complete licensing information.
  7. Module Name:
  8. timer.c
  9. Abstract:
  10. This module implements platform timer services for BIOS machines.
  11. Author:
  12. Evan Green 3-Mar-2014
  13. Environment:
  14. Firmware
  15. --*/
  16. //
  17. // ------------------------------------------------------------------- Includes
  18. //
  19. #include <minoca/lib/types.h>
  20. #include <minoca/fw/acpitabs.h>
  21. #include <uefifw.h>
  22. #include "biosfw.h"
  23. //
  24. // --------------------------------------------------------------------- Macros
  25. //
  26. //
  27. // ---------------------------------------------------------------- Definitions
  28. //
  29. //
  30. // ------------------------------------------------------ Data Type Definitions
  31. //
  32. //
  33. // ----------------------------------------------- Internal Function Prototypes
  34. //
  35. UINT64
  36. EfipPlatformReadTimer (
  37. VOID
  38. );
  39. //
  40. // -------------------------------------------------------------------- Globals
  41. //
  42. //
  43. // Hold on to the location of the PM timer.
  44. //
  45. UINT16 EfiPmTimerPort;
  46. UINT32 EfiPmTimerBitWidth;
  47. //
  48. // ------------------------------------------------------------------ Functions
  49. //
  50. EFIAPI
  51. EFI_STATUS
  52. EfiPlatformSetWatchdogTimer (
  53. UINTN Timeout,
  54. UINT64 WatchdogCode,
  55. UINTN DataSize,
  56. CHAR16 *WatchdogData
  57. )
  58. /*++
  59. Routine Description:
  60. This routine sets the system's watchdog timer.
  61. Arguments:
  62. Timeout - Supplies the number of seconds to set the timer for.
  63. WatchdogCode - Supplies a numeric code to log on a watchdog timeout event.
  64. DataSize - Supplies the size of the watchdog data.
  65. WatchdogData - Supplies an optional buffer that includes a null-terminated
  66. string, optionally followed by additional binary data.
  67. Return Value:
  68. EFI_SUCCESS on success.
  69. EFI_INVALID_PARAMETER if the supplied watchdog code is invalid.
  70. EFI_UNSUPPORTED if there is no watchdog timer.
  71. EFI_DEVICE_ERROR if an error occurred accessing the device hardware.
  72. --*/
  73. {
  74. return EFI_UNSUPPORTED;
  75. }
  76. EFI_STATUS
  77. EfiPlatformInitializeTimers (
  78. UINT32 *ClockTimerInterruptNumber,
  79. EFI_PLATFORM_SERVICE_TIMER_INTERRUPT *ClockTimerServiceRoutine,
  80. EFI_PLATFORM_READ_TIMER *ReadTimerRoutine,
  81. UINT64 *ReadTimerFrequency,
  82. UINT32 *ReadTimerWidth
  83. )
  84. /*++
  85. Routine Description:
  86. This routine initializes platform timer services. There are actually two
  87. different timer services returned in this routine. The periodic timer tick
  88. provides a periodic interrupt. The read timer provides a free running
  89. counter value. These are likely serviced by different timers. For the
  90. periodic timer tick, this routine should start the periodic interrupts
  91. coming in. The periodic rate of the timer can be anything reasonable, as
  92. the time counter will be used to count actual duration. The rate should be
  93. greater than twice the rollover rate of the time counter to ensure proper
  94. time accounting. Interrupts are disabled at the processor core for the
  95. duration of this routine.
  96. Arguments:
  97. ClockTimerInterruptNumber - Supplies a pointer where the interrupt line
  98. number of the periodic timer tick will be returned.
  99. ClockTimerServiceRoutine - Supplies a pointer where a pointer to a routine
  100. called when the periodic timer tick interrupt occurs will be returned.
  101. ReadTimerRoutine - Supplies a pointer where a pointer to a routine
  102. called to read the current timer value will be returned.
  103. ReadTimerFrequency - Supplies the frequency of the counter.
  104. ReadTimerWidth - Supplies a pointer where the read timer bit width will be
  105. returned.
  106. Return Value:
  107. EFI Status code.
  108. --*/
  109. {
  110. PFADT Fadt;
  111. PRSDP Rsdp;
  112. PRSDT Rsdt;
  113. ULONG RsdtTableCount;
  114. PULONG RsdtTableEntry;
  115. UINTN TableIndex;
  116. //
  117. // Find the FADT to figure out where the PM timer is.
  118. //
  119. Rsdp = EfiRsdpPointer;
  120. if (Rsdp == NULL) {
  121. return EFI_UNSUPPORTED;
  122. }
  123. Rsdt = (PRSDT)(UINTN)(Rsdp->RsdtAddress);
  124. RsdtTableCount = (Rsdt->Header.Length - sizeof(DESCRIPTION_HEADER)) /
  125. sizeof(ULONG);
  126. if (RsdtTableCount == 0) {
  127. return EFI_NOT_FOUND;
  128. }
  129. RsdtTableEntry = (PULONG)&(Rsdt->Entries);
  130. for (TableIndex = 0; TableIndex < RsdtTableCount; TableIndex += 1) {
  131. Fadt = (PFADT)RsdtTableEntry[TableIndex];
  132. if (Fadt->Header.Signature == FADT_SIGNATURE) {
  133. break;
  134. }
  135. }
  136. if (TableIndex == RsdtTableCount) {
  137. return EFI_NOT_FOUND;
  138. }
  139. //
  140. // Grab the PM timer port and width out of the FADT table.
  141. //
  142. EfiPmTimerPort = Fadt->PmTimerBlock;
  143. if (EfiPmTimerPort == 0) {
  144. return EFI_UNSUPPORTED;
  145. }
  146. EfiPmTimerBitWidth = 24;
  147. if ((Fadt->Flags & FADT_FLAG_PM_TIMER_32_BITS) != 0) {
  148. EfiPmTimerBitWidth = 32;
  149. }
  150. //
  151. // Clock interrupts are not supported as the BIOS may have 16-bit real mode
  152. // interrupts coming in.
  153. //
  154. *ClockTimerInterruptNumber = 0;
  155. *ClockTimerServiceRoutine = NULL;
  156. *ReadTimerRoutine = EfipPlatformReadTimer;
  157. *ReadTimerFrequency = PM_TIMER_FREQUENCY;
  158. *ReadTimerWidth = EfiPmTimerBitWidth;
  159. return EFI_SUCCESS;
  160. }
  161. VOID
  162. EfiPlatformTerminateTimers (
  163. VOID
  164. )
  165. /*++
  166. Routine Description:
  167. This routine terminates timer services in preparation for the termination
  168. of boot services.
  169. Arguments:
  170. None.
  171. Return Value:
  172. None.
  173. --*/
  174. {
  175. return;
  176. }
  177. //
  178. // --------------------------------------------------------- Internal Functions
  179. //
  180. UINT64
  181. EfipPlatformReadTimer (
  182. VOID
  183. )
  184. /*++
  185. Routine Description:
  186. This routine is called to read the current platform time value. The timer
  187. is assumed to be free running at a constant frequency, and should have a
  188. bit width as reported in the initialize function. The UEFI core will
  189. manage software bit extension out to 64 bits, this routine should just
  190. reporte the hardware timer value.
  191. Arguments:
  192. None.
  193. Return Value:
  194. Returns the hardware timer value.
  195. --*/
  196. {
  197. return EfiIoPortIn32(EfiPmTimerPort);
  198. }