diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 16:49:04 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 16:49:04 +0000 |
commit | 16f504a9dca3fe3b70568f67b7d41241ae485288 (patch) | |
tree | c60f36ada0496ba928b7161059ba5ab1ab224f9d /src/VBox/Devices/EFI/Firmware/PcAtChipsetPkg/Library | |
parent | Initial commit. (diff) | |
download | virtualbox-upstream.tar.xz virtualbox-upstream.zip |
Adding upstream version 7.0.6-dfsg.upstream/7.0.6-dfsgupstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/VBox/Devices/EFI/Firmware/PcAtChipsetPkg/Library')
23 files changed, 1857 insertions, 0 deletions
diff --git a/src/VBox/Devices/EFI/Firmware/PcAtChipsetPkg/Library/AcpiTimerLib/AcpiTimerLib.c b/src/VBox/Devices/EFI/Firmware/PcAtChipsetPkg/Library/AcpiTimerLib/AcpiTimerLib.c new file mode 100644 index 00000000..9d2a9030 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/PcAtChipsetPkg/Library/AcpiTimerLib/AcpiTimerLib.c @@ -0,0 +1,393 @@ +/** @file + ACPI Timer implements one instance of Timer Library. + + Copyright (c) 2013 - 2018, Intel Corporation. All rights reserved.<BR> + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include <Base.h> +#include <Library/TimerLib.h> +#include <Library/BaseLib.h> +#include <Library/PcdLib.h> +#include <Library/PciLib.h> +#include <Library/IoLib.h> +#include <Library/DebugLib.h> +#include <IndustryStandard/Acpi.h> + +GUID mFrequencyHobGuid = { 0x3fca54f6, 0xe1a2, 0x4b20, { 0xbe, 0x76, 0x92, 0x6b, 0x4b, 0x48, 0xbf, 0xaa }}; + +/** + Internal function to retrieves the 64-bit frequency in Hz. + + Internal function to retrieves the 64-bit frequency in Hz. + + @return The frequency in Hz. + +**/ +UINT64 +InternalGetPerformanceCounterFrequency ( + VOID + ); + +/** + The constructor function enables ACPI IO space. + + If ACPI I/O space not enabled, this function will enable it. + It will always return RETURN_SUCCESS. + + @retval EFI_SUCCESS The constructor always returns RETURN_SUCCESS. + +**/ +RETURN_STATUS +EFIAPI +AcpiTimerLibConstructor ( + VOID + ) +{ + UINTN Bus; + UINTN Device; + UINTN Function; + UINTN EnableRegister; + UINT8 EnableMask; + + // + // ASSERT for the invalid PCD values. They must be configured to the real value. + // + ASSERT (PcdGet16 (PcdAcpiIoPciBarRegisterOffset) != 0xFFFF); + ASSERT (PcdGet16 (PcdAcpiIoPortBaseAddress) != 0xFFFF); + + // + // If the register offset to the BAR for the ACPI I/O Port Base Address is 0x0000, then + // no PCI register programming is required to enable access to the ACPI registers + // specified by PcdAcpiIoPortBaseAddress + // + if (PcdGet16 (PcdAcpiIoPciBarRegisterOffset) == 0x0000) { + return RETURN_SUCCESS; + } + + // + // ASSERT for the invalid PCD values. They must be configured to the real value. + // + ASSERT (PcdGet8 (PcdAcpiIoPciDeviceNumber) != 0xFF); + ASSERT (PcdGet8 (PcdAcpiIoPciFunctionNumber) != 0xFF); + ASSERT (PcdGet16 (PcdAcpiIoPciEnableRegisterOffset) != 0xFFFF); + + // + // Retrieve the PCD values for the PCI configuration space required to program the ACPI I/O Port Base Address + // + Bus = PcdGet8 (PcdAcpiIoPciBusNumber); + Device = PcdGet8 (PcdAcpiIoPciDeviceNumber); + Function = PcdGet8 (PcdAcpiIoPciFunctionNumber); + EnableRegister = PcdGet16 (PcdAcpiIoPciEnableRegisterOffset); + EnableMask = PcdGet8 (PcdAcpiIoBarEnableMask); + + // + // If ACPI I/O space is not enabled yet, program ACPI I/O base address and enable it. + // + if ((PciRead8 (PCI_LIB_ADDRESS (Bus, Device, Function, EnableRegister)) & EnableMask) != EnableMask) { + PciWrite16 ( + PCI_LIB_ADDRESS (Bus, Device, Function, PcdGet16 (PcdAcpiIoPciBarRegisterOffset)), + PcdGet16 (PcdAcpiIoPortBaseAddress) + ); + PciOr8 ( + PCI_LIB_ADDRESS (Bus, Device, Function, EnableRegister), + EnableMask + ); + } + + return RETURN_SUCCESS; +} + +/** + Internal function to retrieve the ACPI I/O Port Base Address. + + Internal function to retrieve the ACPI I/O Port Base Address. + + @return The 16-bit ACPI I/O Port Base Address. + +**/ +UINT16 +InternalAcpiGetAcpiTimerIoPort ( + VOID + ) +{ + UINT16 Port; + + Port = PcdGet16 (PcdAcpiIoPortBaseAddress); + + // + // If the register offset to the BAR for the ACPI I/O Port Base Address is not 0x0000, then + // read the PCI register for the ACPI BAR value in case the BAR has been programmed to a + // value other than PcdAcpiIoPortBaseAddress + // + if (PcdGet16 (PcdAcpiIoPciBarRegisterOffset) != 0x0000) { + Port = PciRead16 (PCI_LIB_ADDRESS ( + PcdGet8 (PcdAcpiIoPciBusNumber), + PcdGet8 (PcdAcpiIoPciDeviceNumber), + PcdGet8 (PcdAcpiIoPciFunctionNumber), + PcdGet16 (PcdAcpiIoPciBarRegisterOffset) + )); + } + + return (Port & PcdGet16 (PcdAcpiIoPortBaseAddressMask)) + PcdGet16 (PcdAcpiPm1TmrOffset); +} + +/** + Stalls the CPU for at least the given number of ticks. + + Stalls the CPU for at least the given number of ticks. It's invoked by + MicroSecondDelay() and NanoSecondDelay(). + + @param Delay A period of time to delay in ticks. + +**/ +VOID +InternalAcpiDelay ( + IN UINT32 Delay + ) +{ + UINT16 Port; + UINT32 Ticks; + UINT32 Times; + + Port = InternalAcpiGetAcpiTimerIoPort (); + Times = Delay >> 22; + Delay &= BIT22 - 1; + do { + // + // The target timer count is calculated here + // + Ticks = IoBitFieldRead32 (Port, 0, 23) + Delay; + Delay = BIT22; + // + // Wait until time out + // Delay >= 2^23 could not be handled by this function + // Timer wrap-arounds are handled correctly by this function + // + while (((Ticks - IoBitFieldRead32 (Port, 0, 23)) & BIT23) == 0) { + CpuPause (); + } + } while (Times-- > 0); +} + +/** + Stalls the CPU for at least the given number of microseconds. + + Stalls the CPU for the number of microseconds specified by MicroSeconds. + + @param MicroSeconds The minimum number of microseconds to delay. + + @return MicroSeconds + +**/ +UINTN +EFIAPI +MicroSecondDelay ( + IN UINTN MicroSeconds + ) +{ + InternalAcpiDelay ( + (UINT32)DivU64x32 ( + MultU64x32 ( + MicroSeconds, + ACPI_TIMER_FREQUENCY + ), + 1000000u + ) + ); + return MicroSeconds; +} + +/** + Stalls the CPU for at least the given number of nanoseconds. + + Stalls the CPU for the number of nanoseconds specified by NanoSeconds. + + @param NanoSeconds The minimum number of nanoseconds to delay. + + @return NanoSeconds + +**/ +UINTN +EFIAPI +NanoSecondDelay ( + IN UINTN NanoSeconds + ) +{ + InternalAcpiDelay ( + (UINT32)DivU64x32 ( + MultU64x32 ( + NanoSeconds, + ACPI_TIMER_FREQUENCY + ), + 1000000000u + ) + ); + return NanoSeconds; +} + +/** + Retrieves the current value of a 64-bit free running performance counter. + + Retrieves the current value of a 64-bit free running performance counter. The + counter can either count up by 1 or count down by 1. If the physical + performance counter counts by a larger increment, then the counter values + must be translated. The properties of the counter can be retrieved from + GetPerformanceCounterProperties(). + + @return The current value of the free running performance counter. + +**/ +UINT64 +EFIAPI +GetPerformanceCounter ( + VOID + ) +{ + return AsmReadTsc (); +} + +/** + Retrieves the 64-bit frequency in Hz and the range of performance counter + values. + + If StartValue is not NULL, then the value that the performance counter starts + with immediately after is it rolls over is returned in StartValue. If + EndValue is not NULL, then the value that the performance counter end with + immediately before it rolls over is returned in EndValue. The 64-bit + frequency of the performance counter in Hz is always returned. If StartValue + is less than EndValue, then the performance counter counts up. If StartValue + is greater than EndValue, then the performance counter counts down. For + example, a 64-bit free running counter that counts up would have a StartValue + of 0 and an EndValue of 0xFFFFFFFFFFFFFFFF. A 24-bit free running counter + that counts down would have a StartValue of 0xFFFFFF and an EndValue of 0. + + @param StartValue The value the performance counter starts with when it + rolls over. + @param EndValue The value that the performance counter ends with before + it rolls over. + + @return The frequency in Hz. + +**/ +UINT64 +EFIAPI +GetPerformanceCounterProperties ( + OUT UINT64 *StartValue, OPTIONAL + OUT UINT64 *EndValue OPTIONAL + ) +{ + if (StartValue != NULL) { + *StartValue = 0; + } + + if (EndValue != NULL) { + *EndValue = 0xffffffffffffffffULL; + } + return InternalGetPerformanceCounterFrequency (); +} + +/** + Converts elapsed ticks of performance counter to time in nanoseconds. + + This function converts the elapsed ticks of running performance counter to + time value in unit of nanoseconds. + + @param Ticks The number of elapsed ticks of running performance counter. + + @return The elapsed time in nanoseconds. + +**/ +UINT64 +EFIAPI +GetTimeInNanoSecond ( + IN UINT64 Ticks + ) +{ + UINT64 Frequency; + UINT64 NanoSeconds; + UINT64 Remainder; + INTN Shift; + + Frequency = GetPerformanceCounterProperties (NULL, NULL); + + // + // Ticks + // Time = --------- x 1,000,000,000 + // Frequency + // + NanoSeconds = MultU64x32 (DivU64x64Remainder (Ticks, Frequency, &Remainder), 1000000000u); + + // + // Ensure (Remainder * 1,000,000,000) will not overflow 64-bit. + // Since 2^29 < 1,000,000,000 = 0x3B9ACA00 < 2^30, Remainder should < 2^(64-30) = 2^34, + // i.e. highest bit set in Remainder should <= 33. + // + Shift = MAX (0, HighBitSet64 (Remainder) - 33); + Remainder = RShiftU64 (Remainder, (UINTN) Shift); + Frequency = RShiftU64 (Frequency, (UINTN) Shift); + NanoSeconds += DivU64x64Remainder (MultU64x32 (Remainder, 1000000000u), Frequency, NULL); + + return NanoSeconds; +} + +/** + Calculate TSC frequency. + + The TSC counting frequency is determined by comparing how far it counts + during a 101.4 us period as determined by the ACPI timer. + The ACPI timer is used because it counts at a known frequency. + The TSC is sampled, followed by waiting 363 counts of the ACPI timer, + or 101.4 us. The TSC is then sampled again. The difference multiplied by + 9861 is the TSC frequency. There will be a small error because of the + overhead of reading the ACPI timer. An attempt is made to determine and + compensate for this error. + + @return The number of TSC counts per second. + +**/ +UINT64 +InternalCalculateTscFrequency ( + VOID + ) +{ + UINT64 StartTSC; + UINT64 EndTSC; + UINT16 TimerAddr; + UINT32 Ticks; + UINT64 TscFrequency; + BOOLEAN InterruptState; + + InterruptState = SaveAndDisableInterrupts (); + + TimerAddr = InternalAcpiGetAcpiTimerIoPort (); + // + // Compute the number of ticks to wait to measure TSC frequency. + // Use 363 * 9861 = 3579543 Hz which is within 2 Hz of ACPI_TIMER_FREQUENCY. + // 363 counts is a calibration time of 101.4 uS. + // + Ticks = IoBitFieldRead32 (TimerAddr, 0, 23) + 363; + + StartTSC = AsmReadTsc (); // Get base value for the TSC + // + // Wait until the ACPI timer has counted 101.4 us. + // Timer wrap-arounds are handled correctly by this function. + // When the current ACPI timer value is greater than 'Ticks', + // the while loop will exit. + // + while (((Ticks - IoBitFieldRead32 (TimerAddr, 0, 23)) & BIT23) == 0) { + CpuPause(); + } + EndTSC = AsmReadTsc (); // TSC value 101.4 us later + + TscFrequency = MultU64x32 ( + (EndTSC - StartTSC), // Number of TSC counts in 101.4 us + 9861 // Number of 101.4 us in a second + ); + + SetInterruptState (InterruptState); + + return TscFrequency; +} + diff --git a/src/VBox/Devices/EFI/Firmware/PcAtChipsetPkg/Library/AcpiTimerLib/BaseAcpiTimerLib.c b/src/VBox/Devices/EFI/Firmware/PcAtChipsetPkg/Library/AcpiTimerLib/BaseAcpiTimerLib.c new file mode 100644 index 00000000..436e4509 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/PcAtChipsetPkg/Library/AcpiTimerLib/BaseAcpiTimerLib.c @@ -0,0 +1,47 @@ +/** @file + ACPI Timer implements one instance of Timer Library. + + Copyright (c) 2013 - 2018, Intel Corporation. All rights reserved.<BR> + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include <Base.h> +#include <Library/TimerLib.h> +#include <Library/BaseLib.h> + +/** + Calculate TSC frequency. + + The TSC counting frequency is determined by comparing how far it counts + during a 101.4 us period as determined by the ACPI timer. + The ACPI timer is used because it counts at a known frequency. + The TSC is sampled, followed by waiting 363 counts of the ACPI timer, + or 101.4 us. The TSC is then sampled again. The difference multiplied by + 9861 is the TSC frequency. There will be a small error because of the + overhead of reading the ACPI timer. An attempt is made to determine and + compensate for this error. + + @return The number of TSC counts per second. + +**/ +UINT64 +InternalCalculateTscFrequency ( + VOID + ); + +/** + Internal function to retrieves the 64-bit frequency in Hz. + + Internal function to retrieves the 64-bit frequency in Hz. + + @return The frequency in Hz. + +**/ +UINT64 +InternalGetPerformanceCounterFrequency ( + VOID + ) +{ + return InternalCalculateTscFrequency (); +} diff --git a/src/VBox/Devices/EFI/Firmware/PcAtChipsetPkg/Library/AcpiTimerLib/BaseAcpiTimerLib.inf b/src/VBox/Devices/EFI/Firmware/PcAtChipsetPkg/Library/AcpiTimerLib/BaseAcpiTimerLib.inf new file mode 100644 index 00000000..d5d6c957 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/PcAtChipsetPkg/Library/AcpiTimerLib/BaseAcpiTimerLib.inf @@ -0,0 +1,49 @@ +## @file +# Base ACPI Timer Library +# +# Provides basic timer support using the ACPI timer hardware. The performance +# counter features are provided by the processors time stamp counter. +# +# Note: The implementation uses the lower 24-bits of the ACPI timer and +# is compatible with both 24-bit and 32-bit ACPI timers. +# +# Copyright (c) 2013 - 2018, Intel Corporation. All rights reserved.<BR> +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = BaseAcpiTimerLib + FILE_GUID = 564DE85F-049E-4481-BF7A-CA04D2788CF9 + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = TimerLib|SEC PEI_CORE PEIM + CONSTRUCTOR = AcpiTimerLibConstructor + MODULE_UNI_FILE = BaseAcpiTimerLib.uni + +[Sources] + AcpiTimerLib.c + BaseAcpiTimerLib.c + +[Packages] + MdePkg/MdePkg.dec + PcAtChipsetPkg/PcAtChipsetPkg.dec + +[LibraryClasses] + BaseLib + PcdLib + PciLib + IoLib + DebugLib + +[Pcd] + gPcAtChipsetPkgTokenSpaceGuid.PcdAcpiIoPciBusNumber ## CONSUMES + gPcAtChipsetPkgTokenSpaceGuid.PcdAcpiIoPciDeviceNumber ## CONSUMES + gPcAtChipsetPkgTokenSpaceGuid.PcdAcpiIoPciFunctionNumber ## CONSUMES + gPcAtChipsetPkgTokenSpaceGuid.PcdAcpiIoPciEnableRegisterOffset ## CONSUMES + gPcAtChipsetPkgTokenSpaceGuid.PcdAcpiIoBarEnableMask ## CONSUMES + gPcAtChipsetPkgTokenSpaceGuid.PcdAcpiIoPciBarRegisterOffset ## CONSUMES + gPcAtChipsetPkgTokenSpaceGuid.PcdAcpiIoPortBaseAddress ## CONSUMES + gPcAtChipsetPkgTokenSpaceGuid.PcdAcpiPm1TmrOffset ## CONSUMES + gPcAtChipsetPkgTokenSpaceGuid.PcdAcpiIoPortBaseAddressMask ## CONSUMES diff --git a/src/VBox/Devices/EFI/Firmware/PcAtChipsetPkg/Library/AcpiTimerLib/BaseAcpiTimerLib.uni b/src/VBox/Devices/EFI/Firmware/PcAtChipsetPkg/Library/AcpiTimerLib/BaseAcpiTimerLib.uni new file mode 100644 index 00000000..a9814557 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/PcAtChipsetPkg/Library/AcpiTimerLib/BaseAcpiTimerLib.uni @@ -0,0 +1,17 @@ +// /** @file
+// Base ACPI Timer Library
+//
+// Provides basic timer support using the ACPI timer hardware. The performance
+// counter features are provided by the processors time stamp counter.
+//
+// Copyright (c) 2013 - 2018, Intel Corporation. All rights reserved.<BR>
+//
+// SPDX-License-Identifier: BSD-2-Clause-Patent
+//
+// **/
+
+
+#string STR_MODULE_ABSTRACT #language en-US "ACPI Timer Library"
+
+#string STR_MODULE_DESCRIPTION #language en-US "Provides basic timer support using the ACPI timer hardware."
+
diff --git a/src/VBox/Devices/EFI/Firmware/PcAtChipsetPkg/Library/AcpiTimerLib/DxeAcpiTimerLib.c b/src/VBox/Devices/EFI/Firmware/PcAtChipsetPkg/Library/AcpiTimerLib/DxeAcpiTimerLib.c new file mode 100644 index 00000000..5fe2e865 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/PcAtChipsetPkg/Library/AcpiTimerLib/DxeAcpiTimerLib.c @@ -0,0 +1,31 @@ +/** @file + ACPI Timer implements one instance of Timer Library. + + Copyright (c) 2013 - 2018, Intel Corporation. All rights reserved.<BR> + Copyright (c) Microsoft Corporation. + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include <PiDxe.h> + +#include "DxeStandaloneMmAcpiTimerLib.h" + +/** + The constructor function enables ACPI IO space, and caches PerformanceCounterFrequency. + + @param ImageHandle The firmware allocated handle for the EFI image. + @param SystemTable A pointer to the EFI System Table. + + @retval EFI_SUCCESS The constructor always returns RETURN_SUCCESS. + +**/ +EFI_STATUS +EFIAPI +DxeAcpiTimerLibConstructor ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + return CommonAcpiTimerLibConstructor (); +} diff --git a/src/VBox/Devices/EFI/Firmware/PcAtChipsetPkg/Library/AcpiTimerLib/DxeAcpiTimerLib.inf b/src/VBox/Devices/EFI/Firmware/PcAtChipsetPkg/Library/AcpiTimerLib/DxeAcpiTimerLib.inf new file mode 100644 index 00000000..5568dd30 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/PcAtChipsetPkg/Library/AcpiTimerLib/DxeAcpiTimerLib.inf @@ -0,0 +1,52 @@ +## @file +# DXE ACPI Timer Library +# +# Provides basic timer support using the ACPI timer hardware. The performance +# counter features are provided by the processors time stamp counter. +# +# Note: The implementation uses the lower 24-bits of the ACPI timer and +# is compatible with both 24-bit and 32-bit ACPI timers. +# +# Copyright (c) 2013 - 2018, Intel Corporation. All rights reserved.<BR> +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = DxeAcpiTimerLib + FILE_GUID = E624B98C-845A-4b94-9B50-B20475D552B9 + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + LIBRARY_CLASS = TimerLib|DXE_CORE DXE_DRIVER DXE_RUNTIME_DRIVER DXE_SMM_DRIVER UEFI_APPLICATION UEFI_DRIVER SMM_CORE + CONSTRUCTOR = DxeAcpiTimerLibConstructor + MODULE_UNI_FILE = DxeAcpiTimerLib.uni + +[Sources] + AcpiTimerLib.c + DxeAcpiTimerLib.c + DxeStandaloneMmAcpiTimerLib.c + DxeStandaloneMmAcpiTimerLib.h + +[Packages] + MdePkg/MdePkg.dec + PcAtChipsetPkg/PcAtChipsetPkg.dec + +[LibraryClasses] + BaseLib + PcdLib + PciLib + IoLib + DebugLib + HobLib + +[Pcd] + gPcAtChipsetPkgTokenSpaceGuid.PcdAcpiIoPciBusNumber ## CONSUMES + gPcAtChipsetPkgTokenSpaceGuid.PcdAcpiIoPciDeviceNumber ## CONSUMES + gPcAtChipsetPkgTokenSpaceGuid.PcdAcpiIoPciFunctionNumber ## CONSUMES + gPcAtChipsetPkgTokenSpaceGuid.PcdAcpiIoPciEnableRegisterOffset ## CONSUMES + gPcAtChipsetPkgTokenSpaceGuid.PcdAcpiIoBarEnableMask ## CONSUMES + gPcAtChipsetPkgTokenSpaceGuid.PcdAcpiIoPciBarRegisterOffset ## CONSUMES + gPcAtChipsetPkgTokenSpaceGuid.PcdAcpiIoPortBaseAddress ## CONSUMES + gPcAtChipsetPkgTokenSpaceGuid.PcdAcpiPm1TmrOffset ## CONSUMES + gPcAtChipsetPkgTokenSpaceGuid.PcdAcpiIoPortBaseAddressMask ## CONSUMES diff --git a/src/VBox/Devices/EFI/Firmware/PcAtChipsetPkg/Library/AcpiTimerLib/DxeAcpiTimerLib.uni b/src/VBox/Devices/EFI/Firmware/PcAtChipsetPkg/Library/AcpiTimerLib/DxeAcpiTimerLib.uni new file mode 100644 index 00000000..e732ab6b --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/PcAtChipsetPkg/Library/AcpiTimerLib/DxeAcpiTimerLib.uni @@ -0,0 +1,17 @@ +// /** @file
+// DXE ACPI Timer Library
+//
+// Provides basic timer support using the ACPI timer hardware. The performance
+// counter features are provided by the processors time stamp counter.
+//
+// Copyright (c) 2013 - 2018, Intel Corporation. All rights reserved.<BR>
+//
+// SPDX-License-Identifier: BSD-2-Clause-Patent
+//
+// **/
+
+
+#string STR_MODULE_ABSTRACT #language en-US "ACPI Timer Library"
+
+#string STR_MODULE_DESCRIPTION #language en-US "Provides basic timer support using the ACPI timer hardware."
+
diff --git a/src/VBox/Devices/EFI/Firmware/PcAtChipsetPkg/Library/AcpiTimerLib/DxeStandaloneMmAcpiTimerLib.c b/src/VBox/Devices/EFI/Firmware/PcAtChipsetPkg/Library/AcpiTimerLib/DxeStandaloneMmAcpiTimerLib.c new file mode 100644 index 00000000..de84d6c4 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/PcAtChipsetPkg/Library/AcpiTimerLib/DxeStandaloneMmAcpiTimerLib.c @@ -0,0 +1,101 @@ +/** @file + ACPI Timer implements one instance of Timer Library. + + Copyright (c) 2013 - 2018, Intel Corporation. All rights reserved.<BR> + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include <PiDxe.h> +#include <Library/TimerLib.h> +#include <Library/BaseLib.h> +#include <Library/HobLib.h> + +extern GUID mFrequencyHobGuid; + +/** + The constructor function enables ACPI IO space. + + If ACPI I/O space not enabled, this function will enable it. + It will always return RETURN_SUCCESS. + + @retval EFI_SUCCESS The constructor always returns RETURN_SUCCESS. + +**/ +RETURN_STATUS +EFIAPI +AcpiTimerLibConstructor ( + VOID + ); + +/** + Calculate TSC frequency. + + The TSC counting frequency is determined by comparing how far it counts + during a 101.4 us period as determined by the ACPI timer. + The ACPI timer is used because it counts at a known frequency. + The TSC is sampled, followed by waiting 363 counts of the ACPI timer, + or 101.4 us. The TSC is then sampled again. The difference multiplied by + 9861 is the TSC frequency. There will be a small error because of the + overhead of reading the ACPI timer. An attempt is made to determine and + compensate for this error. + + @return The number of TSC counts per second. + +**/ +UINT64 +InternalCalculateTscFrequency ( + VOID + ); + +// +// Cached performance counter frequency +// +UINT64 mPerformanceCounterFrequency = 0; + +/** + Internal function to retrieves the 64-bit frequency in Hz. + + Internal function to retrieves the 64-bit frequency in Hz. + + @return The frequency in Hz. + +**/ +UINT64 +InternalGetPerformanceCounterFrequency ( + VOID + ) +{ + return mPerformanceCounterFrequency; +} + +/** + The constructor function enables ACPI IO space, and caches PerformanceCounterFrequency. + + @retval EFI_SUCCESS The constructor always returns RETURN_SUCCESS. + +**/ +EFI_STATUS +CommonAcpiTimerLibConstructor ( + VOID + ) +{ + EFI_HOB_GUID_TYPE *GuidHob; + + // + // Enable ACPI IO space. + // + AcpiTimerLibConstructor (); + + // + // Initialize PerformanceCounterFrequency + // + GuidHob = GetFirstGuidHob (&mFrequencyHobGuid); + if (GuidHob != NULL) { + mPerformanceCounterFrequency = *(UINT64*)GET_GUID_HOB_DATA (GuidHob); + } else { + mPerformanceCounterFrequency = InternalCalculateTscFrequency (); + } + + return EFI_SUCCESS; +} diff --git a/src/VBox/Devices/EFI/Firmware/PcAtChipsetPkg/Library/AcpiTimerLib/DxeStandaloneMmAcpiTimerLib.h b/src/VBox/Devices/EFI/Firmware/PcAtChipsetPkg/Library/AcpiTimerLib/DxeStandaloneMmAcpiTimerLib.h new file mode 100644 index 00000000..981d41e3 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/PcAtChipsetPkg/Library/AcpiTimerLib/DxeStandaloneMmAcpiTimerLib.h @@ -0,0 +1,24 @@ +/** @file + Header file internal to ACPI TimerLib. + +Copyright (c) Microsoft Corporation. +SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + +#ifndef _DXE_STANDALONE_MM_ACPI_TIMER_LIB_H_ +#define _DXE_STANDALONE_MM_ACPI_TIMER_LIB_H_ + +/** + The constructor function enables ACPI IO space, and caches PerformanceCounterFrequency. + + @retval EFI_SUCCESS The constructor always returns RETURN_SUCCESS. + +**/ +EFI_STATUS +CommonAcpiTimerLibConstructor ( + VOID + ); + +#endif diff --git a/src/VBox/Devices/EFI/Firmware/PcAtChipsetPkg/Library/AcpiTimerLib/PeiAcpiTimerLib.c b/src/VBox/Devices/EFI/Firmware/PcAtChipsetPkg/Library/AcpiTimerLib/PeiAcpiTimerLib.c new file mode 100644 index 00000000..05dc81b2 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/PcAtChipsetPkg/Library/AcpiTimerLib/PeiAcpiTimerLib.c @@ -0,0 +1,64 @@ +/** @file + ACPI Timer implements one instance of Timer Library. + + Copyright (c) 2013 - 2018, Intel Corporation. All rights reserved.<BR> + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include <PiPei.h> +#include <Library/TimerLib.h> +#include <Library/BaseLib.h> +#include <Library/HobLib.h> +#include <Library/DebugLib.h> + +extern GUID mFrequencyHobGuid; + +/** + Calculate TSC frequency. + + The TSC counting frequency is determined by comparing how far it counts + during a 101.4 us period as determined by the ACPI timer. + The ACPI timer is used because it counts at a known frequency. + The TSC is sampled, followed by waiting 363 counts of the ACPI timer, + or 101.4 us. The TSC is then sampled again. The difference multiplied by + 9861 is the TSC frequency. There will be a small error because of the + overhead of reading the ACPI timer. An attempt is made to determine and + compensate for this error. + + @return The number of TSC counts per second. + +**/ +UINT64 +InternalCalculateTscFrequency ( + VOID + ); + +/** + Internal function to retrieves the 64-bit frequency in Hz. + + Internal function to retrieves the 64-bit frequency in Hz. + + @return The frequency in Hz. + +**/ +UINT64 +InternalGetPerformanceCounterFrequency ( + VOID + ) +{ + UINT64 *PerformanceCounterFrequency; + EFI_HOB_GUID_TYPE *GuidHob; + + PerformanceCounterFrequency = NULL; + GuidHob = GetFirstGuidHob (&mFrequencyHobGuid); + if (GuidHob == NULL) { + PerformanceCounterFrequency = (UINT64*)BuildGuidHob(&mFrequencyHobGuid, sizeof (*PerformanceCounterFrequency)); + ASSERT (PerformanceCounterFrequency != NULL); + *PerformanceCounterFrequency = InternalCalculateTscFrequency (); + } else { + PerformanceCounterFrequency = (UINT64*)GET_GUID_HOB_DATA (GuidHob); + } + + return *PerformanceCounterFrequency; +} diff --git a/src/VBox/Devices/EFI/Firmware/PcAtChipsetPkg/Library/AcpiTimerLib/PeiAcpiTimerLib.inf b/src/VBox/Devices/EFI/Firmware/PcAtChipsetPkg/Library/AcpiTimerLib/PeiAcpiTimerLib.inf new file mode 100644 index 00000000..99f71764 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/PcAtChipsetPkg/Library/AcpiTimerLib/PeiAcpiTimerLib.inf @@ -0,0 +1,50 @@ +## @file +# PEI ACPI Timer Library +# +# Provides basic timer support using the ACPI timer hardware. The performance +# counter features are provided by the processors time stamp counter. +# +# Note: The implementation uses the lower 24-bits of the ACPI timer and +# is compatible with both 24-bit and 32-bit ACPI timers. +# +# Copyright (c) 2013 - 2018, Intel Corporation. All rights reserved.<BR> +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = PeiAcpiTimerLib + FILE_GUID = 3FCA54F6-E1A2-4B20-BE76-926B4B48BFAA + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = TimerLib|PEI_CORE PEIM + CONSTRUCTOR = AcpiTimerLibConstructor + MODULE_UNI_FILE = PeiAcpiTimerLib.uni + +[Sources] + AcpiTimerLib.c + PeiAcpiTimerLib.c + +[Packages] + MdePkg/MdePkg.dec + PcAtChipsetPkg/PcAtChipsetPkg.dec + +[LibraryClasses] + BaseLib + PcdLib + PciLib + IoLib + DebugLib + HobLib + +[Pcd] + gPcAtChipsetPkgTokenSpaceGuid.PcdAcpiIoPciBusNumber ## CONSUMES + gPcAtChipsetPkgTokenSpaceGuid.PcdAcpiIoPciDeviceNumber ## CONSUMES + gPcAtChipsetPkgTokenSpaceGuid.PcdAcpiIoPciFunctionNumber ## CONSUMES + gPcAtChipsetPkgTokenSpaceGuid.PcdAcpiIoPciEnableRegisterOffset ## CONSUMES + gPcAtChipsetPkgTokenSpaceGuid.PcdAcpiIoBarEnableMask ## CONSUMES + gPcAtChipsetPkgTokenSpaceGuid.PcdAcpiIoPciBarRegisterOffset ## CONSUMES + gPcAtChipsetPkgTokenSpaceGuid.PcdAcpiIoPortBaseAddress ## CONSUMES + gPcAtChipsetPkgTokenSpaceGuid.PcdAcpiPm1TmrOffset ## CONSUMES + gPcAtChipsetPkgTokenSpaceGuid.PcdAcpiIoPortBaseAddressMask ## CONSUMES diff --git a/src/VBox/Devices/EFI/Firmware/PcAtChipsetPkg/Library/AcpiTimerLib/PeiAcpiTimerLib.uni b/src/VBox/Devices/EFI/Firmware/PcAtChipsetPkg/Library/AcpiTimerLib/PeiAcpiTimerLib.uni new file mode 100644 index 00000000..b6e96e4e --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/PcAtChipsetPkg/Library/AcpiTimerLib/PeiAcpiTimerLib.uni @@ -0,0 +1,17 @@ +// /** @file
+// PEI ACPI Timer Library
+//
+// Provides basic timer support using the ACPI timer hardware. The performance
+// counter features are provided by the processors time stamp counter.
+//
+// Copyright (c) 2018, Intel Corporation. All rights reserved.<BR>
+//
+// SPDX-License-Identifier: BSD-2-Clause-Patent
+//
+// **/
+
+
+#string STR_MODULE_ABSTRACT #language en-US "ACPI Timer Library"
+
+#string STR_MODULE_DESCRIPTION #language en-US "Provides basic timer support using the ACPI timer hardware."
+
diff --git a/src/VBox/Devices/EFI/Firmware/PcAtChipsetPkg/Library/AcpiTimerLib/StandaloneMmAcpiTimerLib.c b/src/VBox/Devices/EFI/Firmware/PcAtChipsetPkg/Library/AcpiTimerLib/StandaloneMmAcpiTimerLib.c new file mode 100644 index 00000000..3484eff3 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/PcAtChipsetPkg/Library/AcpiTimerLib/StandaloneMmAcpiTimerLib.c @@ -0,0 +1,31 @@ +/** @file + ACPI Timer implements one instance of Timer Library. + + Copyright (c) 2013 - 2018, Intel Corporation. All rights reserved.<BR> + Copyright (c) Microsoft Corporation. + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include <PiMm.h> + +#include "DxeStandaloneMmAcpiTimerLib.h" + +/** + The constructor function enables ACPI IO space, and caches PerformanceCounterFrequency. + + @param ImageHandle The firmware allocated handle for the EFI image. + @param SystemTable A pointer to the EFI System Table. + + @retval EFI_SUCCESS The constructor always returns RETURN_SUCCESS. + +**/ +EFI_STATUS +EFIAPI +StandaloneMmAcpiTimerLibConstructor ( + IN EFI_HANDLE ImageHandle, + IN EFI_MM_SYSTEM_TABLE *SystemTable + ) +{ + return CommonAcpiTimerLibConstructor (); +} diff --git a/src/VBox/Devices/EFI/Firmware/PcAtChipsetPkg/Library/AcpiTimerLib/StandaloneMmAcpiTimerLib.inf b/src/VBox/Devices/EFI/Firmware/PcAtChipsetPkg/Library/AcpiTimerLib/StandaloneMmAcpiTimerLib.inf new file mode 100644 index 00000000..2628c744 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/PcAtChipsetPkg/Library/AcpiTimerLib/StandaloneMmAcpiTimerLib.inf @@ -0,0 +1,53 @@ +## @file +# Standalone MM ACPI Timer Library +# +# Provides basic timer support using the ACPI timer hardware. The performance +# counter features are provided by the processors time stamp counter. +# +# Note: The implementation uses the lower 24-bits of the ACPI timer and +# is compatible with both 24-bit and 32-bit ACPI timers. +# +# Copyright (c) 2013 - 2018, Intel Corporation. All rights reserved.<BR> +# Copyright (c) Microsoft Corporation. +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = StandaloneMmAcpiTimerLib + FILE_GUID = C771858D-AF09-4D1A-B2F3-C7F081C3F076 + MODULE_TYPE = MM_STANDALONE + VERSION_STRING = 1.0 + PI_SPECIFICATION_VERSION = 0x00010032 + LIBRARY_CLASS = TimerLib|MM_CORE_STANDALONE MM_STANDALONE + CONSTRUCTOR = StandaloneMmAcpiTimerLibConstructor + +[Sources] + AcpiTimerLib.c + StandaloneMmAcpiTimerLib.c + DxeStandaloneMmAcpiTimerLib.c + DxeStandaloneMmAcpiTimerLib.h + +[Packages] + MdePkg/MdePkg.dec + PcAtChipsetPkg/PcAtChipsetPkg.dec + +[LibraryClasses] + BaseLib + PcdLib + PciLib + IoLib + DebugLib + HobLib + +[Pcd] + gPcAtChipsetPkgTokenSpaceGuid.PcdAcpiIoPciBusNumber ## CONSUMES + gPcAtChipsetPkgTokenSpaceGuid.PcdAcpiIoPciDeviceNumber ## CONSUMES + gPcAtChipsetPkgTokenSpaceGuid.PcdAcpiIoPciFunctionNumber ## CONSUMES + gPcAtChipsetPkgTokenSpaceGuid.PcdAcpiIoPciEnableRegisterOffset ## CONSUMES + gPcAtChipsetPkgTokenSpaceGuid.PcdAcpiIoBarEnableMask ## CONSUMES + gPcAtChipsetPkgTokenSpaceGuid.PcdAcpiIoPciBarRegisterOffset ## CONSUMES + gPcAtChipsetPkgTokenSpaceGuid.PcdAcpiIoPortBaseAddress ## CONSUMES + gPcAtChipsetPkgTokenSpaceGuid.PcdAcpiPm1TmrOffset ## CONSUMES + gPcAtChipsetPkgTokenSpaceGuid.PcdAcpiIoPortBaseAddressMask ## CONSUMES diff --git a/src/VBox/Devices/EFI/Firmware/PcAtChipsetPkg/Library/BaseIoApicLib/BaseIoApicLib.inf b/src/VBox/Devices/EFI/Firmware/PcAtChipsetPkg/Library/BaseIoApicLib/BaseIoApicLib.inf new file mode 100644 index 00000000..441af96f --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/PcAtChipsetPkg/Library/BaseIoApicLib/BaseIoApicLib.inf @@ -0,0 +1,34 @@ +## @file +# Library instance for I/O APIC library class +# +# Copyright (c) 2011 - 2014, Intel Corporation. All rights reserved.<BR> +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = BaseIoApicLib + MODULE_UNI_FILE = BaseIoApicLib.uni + FILE_GUID = 58ED6E5A-E36A-462a-9ED6-6E62C9A26DF8 + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = IoApicLib + +[Packages] + MdePkg/MdePkg.dec + UefiCpuPkg/UefiCpuPkg.dec + PcAtChipsetPkg/PcAtChipsetPkg.dec + +[LibraryClasses] + DebugLib + IoLib + PcdLib + LocalApicLib + +[Sources] + IoApicLib.c + +[Pcd] + gPcAtChipsetPkgTokenSpaceGuid.PcdIoApicBaseAddress ## CONSUMES + diff --git a/src/VBox/Devices/EFI/Firmware/PcAtChipsetPkg/Library/BaseIoApicLib/BaseIoApicLib.uni b/src/VBox/Devices/EFI/Firmware/PcAtChipsetPkg/Library/BaseIoApicLib/BaseIoApicLib.uni new file mode 100644 index 00000000..5931b252 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/PcAtChipsetPkg/Library/BaseIoApicLib/BaseIoApicLib.uni @@ -0,0 +1,16 @@ +// /** @file
+// Library instance for I/O APIC library class
+//
+// Library instance for I/O APIC library class.
+//
+// Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.<BR>
+//
+// SPDX-License-Identifier: BSD-2-Clause-Patent
+//
+// **/
+
+
+#string STR_MODULE_ABSTRACT #language en-US "Library instance for I/O APIC library class"
+
+#string STR_MODULE_DESCRIPTION #language en-US "Library instance for I/O APIC library class."
+
diff --git a/src/VBox/Devices/EFI/Firmware/PcAtChipsetPkg/Library/BaseIoApicLib/IoApicLib.c b/src/VBox/Devices/EFI/Firmware/PcAtChipsetPkg/Library/BaseIoApicLib/IoApicLib.c new file mode 100644 index 00000000..61bc3bf6 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/PcAtChipsetPkg/Library/BaseIoApicLib/IoApicLib.c @@ -0,0 +1,152 @@ +/** @file + I/O APIC library. + + I/O APIC library assumes I/O APIC is enabled. It does not + handles cases where I/O APIC is disabled. + + Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.<BR> + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include <Base.h> + +#include <Library/IoApicLib.h> + +#include <Library/DebugLib.h> +#include <Library/PcdLib.h> +#include <Library/IoLib.h> +#include <Library/LocalApicLib.h> + +#include <Register/IoApic.h> + +/** + Read a 32-bit I/O APIC register. + + If Index is >= 0x100, then ASSERT(). + + @param Index Specifies the I/O APIC register to read. + + @return The 32-bit value read from the I/O APIC register specified by Index. +**/ +UINT32 +EFIAPI +IoApicRead ( + IN UINTN Index + ) +{ + ASSERT (Index < 0x100); + MmioWrite8 (PcdGet32 (PcdIoApicBaseAddress) + IOAPIC_INDEX_OFFSET, (UINT8)Index); + return MmioRead32 (PcdGet32 (PcdIoApicBaseAddress) + IOAPIC_DATA_OFFSET); +} + +/** + Write a 32-bit I/O APIC register. + + If Index is >= 0x100, then ASSERT(). + + @param Index Specifies the I/O APIC register to write. + @param Value Specifies the value to write to the I/O APIC register specified by Index. + + @return The 32-bit value written to I/O APIC register specified by Index. +**/ +UINT32 +EFIAPI +IoApicWrite ( + IN UINTN Index, + IN UINT32 Value + ) +{ + ASSERT (Index < 0x100); + MmioWrite8 (PcdGet32 (PcdIoApicBaseAddress) + IOAPIC_INDEX_OFFSET, (UINT8)Index); + return MmioWrite32 (PcdGet32 (PcdIoApicBaseAddress) + IOAPIC_DATA_OFFSET, Value); +} + +/** + Set the interrupt mask of an I/O APIC interrupt. + + If Irq is larger than the maximum number I/O APIC redirection entries, then ASSERT(). + + @param Irq Specifies the I/O APIC interrupt to enable or disable. + @param Enable If TRUE, then enable the I/O APIC interrupt specified by Irq. + If FALSE, then disable the I/O APIC interrupt specified by Irq. +**/ +VOID +EFIAPI +IoApicEnableInterrupt ( + IN UINTN Irq, + IN BOOLEAN Enable + ) +{ + IO_APIC_VERSION_REGISTER Version; + IO_APIC_REDIRECTION_TABLE_ENTRY Entry; + + Version.Uint32 = IoApicRead (IO_APIC_VERSION_REGISTER_INDEX); + ASSERT (Version.Bits.MaximumRedirectionEntry < 0xF0); + ASSERT (Irq <= Version.Bits.MaximumRedirectionEntry); + + Entry.Uint32.Low = IoApicRead (IO_APIC_REDIRECTION_TABLE_ENTRY_INDEX + Irq * 2); + Entry.Bits.Mask = Enable ? 0 : 1; + IoApicWrite (IO_APIC_REDIRECTION_TABLE_ENTRY_INDEX + Irq * 2, Entry.Uint32.Low); +} + +/** + Configures an I/O APIC interrupt. + + Configure an I/O APIC Redirection Table Entry to deliver an interrupt in physical + mode to the Local APIC of the currently executing CPU. The default state of the + entry is for the interrupt to be disabled (masked). IoApicEnableInterrupts() must + be used to enable(unmask) the I/O APIC Interrupt. + + If Irq is larger than the maximum number I/O APIC redirection entries, then ASSERT(). + If Vector >= 0x100, then ASSERT(). + If DeliveryMode is not supported, then ASSERT(). + + @param Irq Specifies the I/O APIC interrupt to initialize. + @param Vector The 8-bit interrupt vector associated with the I/O APIC + Interrupt. Must be in the range 0x10..0xFE. + @param DeliveryMode A 3-bit value that specifies how the recept of the I/O APIC + interrupt is handled. The only supported values are: + 0: IO_APIC_DELIVERY_MODE_FIXED + 1: IO_APIC_DELIVERY_MODE_LOWEST_PRIORITY + 2: IO_APIC_DELIVERY_MODE_SMI + 4: IO_APIC_DELIVERY_MODE_NMI + 5: IO_APIC_DELIVERY_MODE_INIT + 7: IO_APIC_DELIVERY_MODE_EXTINT + @param LevelTriggered TRUE specifies a level triggered interrupt. + FALSE specifies an edge triggered interrupt. + @param AssertionLevel TRUE specified an active high interrupt. + FALSE specifies an active low interrupt. +**/ +VOID +EFIAPI +IoApicConfigureInterrupt ( + IN UINTN Irq, + IN UINTN Vector, + IN UINTN DeliveryMode, + IN BOOLEAN LevelTriggered, + IN BOOLEAN AssertionLevel + ) +{ + IO_APIC_VERSION_REGISTER Version; + IO_APIC_REDIRECTION_TABLE_ENTRY Entry; + + Version.Uint32 = IoApicRead (IO_APIC_VERSION_REGISTER_INDEX); + ASSERT (Version.Bits.MaximumRedirectionEntry < 0xF0); + ASSERT (Irq <= Version.Bits.MaximumRedirectionEntry); + ASSERT (Vector <= 0xFF); + ASSERT (DeliveryMode < 8 && DeliveryMode != 6 && DeliveryMode != 3); + + Entry.Uint32.Low = IoApicRead (IO_APIC_REDIRECTION_TABLE_ENTRY_INDEX + Irq * 2); + Entry.Bits.Vector = (UINT8)Vector; + Entry.Bits.DeliveryMode = (UINT32)DeliveryMode; + Entry.Bits.DestinationMode = 0; + Entry.Bits.Polarity = AssertionLevel ? 0 : 1; + Entry.Bits.TriggerMode = LevelTriggered ? 1 : 0; + Entry.Bits.Mask = 1; + IoApicWrite (IO_APIC_REDIRECTION_TABLE_ENTRY_INDEX + Irq * 2, Entry.Uint32.Low); + + Entry.Uint32.High = IoApicRead (IO_APIC_REDIRECTION_TABLE_ENTRY_INDEX + Irq * 2 + 1); + Entry.Bits.DestinationID = GetApicId (); + IoApicWrite (IO_APIC_REDIRECTION_TABLE_ENTRY_INDEX + Irq * 2 + 1, Entry.Uint32.High); +} diff --git a/src/VBox/Devices/EFI/Firmware/PcAtChipsetPkg/Library/ResetSystemLib/ResetSystemLib.c b/src/VBox/Devices/EFI/Firmware/PcAtChipsetPkg/Library/ResetSystemLib/ResetSystemLib.c new file mode 100644 index 00000000..d8021df0 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/PcAtChipsetPkg/Library/ResetSystemLib/ResetSystemLib.c @@ -0,0 +1,130 @@ +/** @file + Reset System Library functions for PCAT platforms + + Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR> + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include <Base.h> + +#include <Uefi/UefiBaseType.h> +#include <Uefi/UefiMultiPhase.h> + +#include <Library/DebugLib.h> +#include <Library/IoLib.h> + +/** + Calling this function causes a system-wide reset. This sets + all circuitry within the system to its initial state. This type of reset + is asynchronous to system operation and operates without regard to + cycle boundaries. + + System reset should not return, if it returns, it means the system does + not support cold reset. +**/ +VOID +EFIAPI +ResetCold ( + VOID + ) +{ + IoWrite8 ((UINTN) PcdGet64 (PcdResetControlRegister), PcdGet8 (PcdResetControlValueColdReset)); +} + +/** + Calling this function causes a system-wide initialization. The processors + are set to their initial state, and pending cycles are not corrupted. + + System reset should not return, if it returns, it means the system does + not support warm reset. +**/ +VOID +EFIAPI +ResetWarm ( + VOID + ) +{ + IoWrite8 ((UINTN) PcdGet64 (PcdResetControlRegister), PcdGet8 (PcdResetControlValueColdReset)); +} + +/** + Calling this function causes the system to enter a power state equivalent + to the ACPI G2/S5 or G3 states. + + System shutdown should not return, if it returns, it means the system does + not support shut down reset. +**/ +VOID +EFIAPI +ResetShutdown ( + VOID + ) +{ + ASSERT (FALSE); +} + + +/** + This function causes a systemwide reset. The exact type of the reset is + defined by the EFI_GUID that follows the Null-terminated Unicode string passed + into ResetData. If the platform does not recognize the EFI_GUID in ResetData + the platform must pick a supported reset type to perform.The platform may + optionally log the parameters from any non-normal reset that occurs. + + @param[in] DataSize The size, in bytes, of ResetData. + @param[in] ResetData The data buffer starts with a Null-terminated string, + followed by the EFI_GUID. +**/ +VOID +EFIAPI +ResetPlatformSpecific ( + IN UINTN DataSize, + IN VOID *ResetData + ) +{ + ResetCold (); +} + +/** + The ResetSystem function resets the entire platform. + + @param[in] ResetType The type of reset to perform. + @param[in] ResetStatus The status code for the reset. + @param[in] DataSize The size, in bytes, of ResetData. + @param[in] ResetData For a ResetType of EfiResetCold, EfiResetWarm, or EfiResetShutdown + the data buffer starts with a Null-terminated string, optionally + followed by additional binary data. The string is a description + that the caller may use to further indicate the reason for the + system reset. +**/ +VOID +EFIAPI +ResetSystem ( + IN EFI_RESET_TYPE ResetType, + IN EFI_STATUS ResetStatus, + IN UINTN DataSize, + IN VOID *ResetData OPTIONAL + ) +{ + switch (ResetType) { + case EfiResetWarm: + ResetWarm (); + break; + + case EfiResetCold: + ResetCold (); + break; + + case EfiResetShutdown: + ResetShutdown (); + return; + + case EfiResetPlatformSpecific: + ResetPlatformSpecific (DataSize, ResetData); + return; + + default: + return; + } +} diff --git a/src/VBox/Devices/EFI/Firmware/PcAtChipsetPkg/Library/ResetSystemLib/ResetSystemLib.inf b/src/VBox/Devices/EFI/Firmware/PcAtChipsetPkg/Library/ResetSystemLib/ResetSystemLib.inf new file mode 100644 index 00000000..375d3dcd --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/PcAtChipsetPkg/Library/ResetSystemLib/ResetSystemLib.inf @@ -0,0 +1,37 @@ +## @file +# Library instance for ResetSystem library class for PCAT systems +# +# Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR> +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = ResetSystemLib + MODULE_UNI_FILE = ResetSystemLib.uni + FILE_GUID = EC4F3E59-F879-418b-9E4C-7D6F434714A0 + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = ResetSystemLib + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 +# + +[Sources] + ResetSystemLib.c + +[Packages] + MdePkg/MdePkg.dec + PcAtChipsetPkg/PcAtChipsetPkg.dec + +[LibraryClasses] + DebugLib + IoLib + +[Pcd] + gPcAtChipsetPkgTokenSpaceGuid.PcdResetControlRegister ## CONSUMES + gPcAtChipsetPkgTokenSpaceGuid.PcdResetControlValueColdReset ## CONSUMES diff --git a/src/VBox/Devices/EFI/Firmware/PcAtChipsetPkg/Library/ResetSystemLib/ResetSystemLib.uni b/src/VBox/Devices/EFI/Firmware/PcAtChipsetPkg/Library/ResetSystemLib/ResetSystemLib.uni new file mode 100644 index 00000000..ea2a9103 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/PcAtChipsetPkg/Library/ResetSystemLib/ResetSystemLib.uni @@ -0,0 +1,16 @@ +// /** @file
+// Library instance for ResetSystem library class for PCAT systems
+//
+// Library instance for ResetSystem library class for PCAT systems
+//
+// Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
+//
+// SPDX-License-Identifier: BSD-2-Clause-Patent
+//
+// **/
+
+
+#string STR_MODULE_ABSTRACT #language en-US "Library instance for ResetSystem library class for PCAT systems"
+
+#string STR_MODULE_DESCRIPTION #language en-US "Library instance for ResetSystem library class for PCAT systems"
+
diff --git a/src/VBox/Devices/EFI/Firmware/PcAtChipsetPkg/Library/SerialIoLib/PcAtSerialPortLib.uni b/src/VBox/Devices/EFI/Firmware/PcAtChipsetPkg/Library/SerialIoLib/PcAtSerialPortLib.uni new file mode 100644 index 00000000..2efd21ca --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/PcAtChipsetPkg/Library/SerialIoLib/PcAtSerialPortLib.uni @@ -0,0 +1,16 @@ +// /** @file
+// Library instance for SerialIo library class
+//
+// Library instance for SerialIO library class.
+//
+// Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
+//
+// SPDX-License-Identifier: BSD-2-Clause-Patent
+//
+// **/
+
+
+#string STR_MODULE_ABSTRACT #language en-US "Library instance for SerialIO library class"
+
+#string STR_MODULE_DESCRIPTION #language en-US "Library instance for SerialIO library class."
+
diff --git a/src/VBox/Devices/EFI/Firmware/PcAtChipsetPkg/Library/SerialIoLib/SerialIoLib.inf b/src/VBox/Devices/EFI/Firmware/PcAtChipsetPkg/Library/SerialIoLib/SerialIoLib.inf new file mode 100644 index 00000000..6d3bad36 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/PcAtChipsetPkg/Library/SerialIoLib/SerialIoLib.inf @@ -0,0 +1,27 @@ +## @file +# Library instance for SerialIo library class +# +# Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.<BR> +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = PcAtSerialPortLib + MODULE_UNI_FILE = PcAtSerialPortLib.uni + FILE_GUID = 1B25AF84-1EA8-4b52-894E-BFA6880B97FF + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = SerialPortLib + +[Packages] + MdePkg/MdePkg.dec + +[LibraryClasses] + BaseLib + IoLib + +[Sources] + SerialPortLib.c + diff --git a/src/VBox/Devices/EFI/Firmware/PcAtChipsetPkg/Library/SerialIoLib/SerialPortLib.c b/src/VBox/Devices/EFI/Firmware/PcAtChipsetPkg/Library/SerialIoLib/SerialPortLib.c new file mode 100644 index 00000000..6c126504 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/PcAtChipsetPkg/Library/SerialIoLib/SerialPortLib.c @@ -0,0 +1,483 @@ +/** @file + UART Serial Port library functions + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR> + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include <Base.h> +#include <Library/IoLib.h> +#include <Library/SerialPortLib.h> + +//--------------------------------------------- +// UART Register Offsets +//--------------------------------------------- +#define BAUD_LOW_OFFSET 0x00 +#define BAUD_HIGH_OFFSET 0x01 +#define IER_OFFSET 0x01 +#define LCR_SHADOW_OFFSET 0x01 +#define FCR_SHADOW_OFFSET 0x02 +#define IR_CONTROL_OFFSET 0x02 +#define FCR_OFFSET 0x02 +#define EIR_OFFSET 0x02 +#define BSR_OFFSET 0x03 +#define LCR_OFFSET 0x03 +#define MCR_OFFSET 0x04 +#define LSR_OFFSET 0x05 +#define MSR_OFFSET 0x06 + +//--------------------------------------------- +// UART Register Bit Defines +//--------------------------------------------- +#define LSR_TXRDY 0x20 +#define LSR_RXDA 0x01 +#define DLAB 0x01 +#define MCR_DTRC 0x01 +#define MCR_RTS 0x02 +#define MSR_CTS 0x10 +#define MSR_DSR 0x20 +#define MSR_RI 0x40 +#define MSR_DCD 0x80 + +//--------------------------------------------- +// UART Settings +//--------------------------------------------- +UINT16 gUartBase = 0x3F8; +UINTN gBps = 115200; +UINT8 gData = 8; +UINT8 gStop = 1; +UINT8 gParity = 0; +UINT8 gBreakSet = 0; + +/** + Initialize the serial device hardware. + + If no initialization is required, then return RETURN_SUCCESS. + If the serial device was successfully initialized, then return RETURN_SUCCESS. + If the serial device could not be initialized, then return RETURN_DEVICE_ERROR. + + @retval RETURN_SUCCESS The serial device was initialized. + @retval RETURN_DEVICE_ERROR The serial device could not be initialized. + +**/ +RETURN_STATUS +EFIAPI +SerialPortInitialize ( + VOID + ) +{ + UINTN Divisor; + UINT8 OutputData; + UINT8 Data; + + // + // Map 5..8 to 0..3 + // + Data = (UINT8) (gData - (UINT8) 5); + + // + // Calculate divisor for baud generator + // + Divisor = 115200 / gBps; + + // + // Set communications format + // + OutputData = (UINT8) ((DLAB << 7) | (gBreakSet << 6) | (gParity << 3) | (gStop << 2) | Data); + IoWrite8 (gUartBase + LCR_OFFSET, OutputData); + + // + // Configure baud rate + // + IoWrite8 (gUartBase + BAUD_HIGH_OFFSET, (UINT8) (Divisor >> 8)); + IoWrite8 (gUartBase + BAUD_LOW_OFFSET, (UINT8) (Divisor & 0xff)); + + // + // Switch back to bank 0 + // + OutputData = (UINT8) ( (gBreakSet << 6) | (gParity << 3) | (gStop << 2) | Data); + IoWrite8 (gUartBase + LCR_OFFSET, OutputData); + + return RETURN_SUCCESS; +} + +/** + Write data from buffer to serial device. + + Writes NumberOfBytes data bytes from Buffer to the serial device. + The number of bytes actually written to the serial device is returned. + If the return value is less than NumberOfBytes, then the write operation failed. + + If Buffer is NULL, then ASSERT(). + + If NumberOfBytes is zero, then return 0. + + @param Buffer Pointer to the data buffer to be written. + @param NumberOfBytes Number of bytes to written to the serial device. + + @retval 0 NumberOfBytes is 0. + @retval >0 The number of bytes written to the serial device. + If this value is less than NumberOfBytes, then the write operation failed. + +**/ +UINTN +EFIAPI +SerialPortWrite ( + IN UINT8 *Buffer, + IN UINTN NumberOfBytes +) +{ + UINTN Result; + UINT8 Data; + + if (Buffer == NULL) { + return 0; + } + + Result = NumberOfBytes; + + while ((NumberOfBytes--) != 0) { + // + // Wait for the serial port to be ready. + // + do { + Data = IoRead8 ((UINT16) gUartBase + LSR_OFFSET); + } while ((Data & LSR_TXRDY) == 0); + IoWrite8 ((UINT16) gUartBase, *Buffer++); + } + + return Result; +} + + +/** + Reads data from a serial device into a buffer. + + @param Buffer Pointer to the data buffer to store the data read from the serial device. + @param NumberOfBytes Number of bytes to read from the serial device. + + @retval 0 NumberOfBytes is 0. + @retval >0 The number of bytes read from the serial device. + If this value is less than NumberOfBytes, then the read operation failed. + +**/ +UINTN +EFIAPI +SerialPortRead ( + OUT UINT8 *Buffer, + IN UINTN NumberOfBytes +) +{ + UINTN Result; + UINT8 Data; + + if (NULL == Buffer) { + return 0; + } + + Result = NumberOfBytes; + + while ((NumberOfBytes--) != 0) { + // + // Wait for the serial port to be ready. + // + do { + Data = IoRead8 ((UINT16) gUartBase + LSR_OFFSET); + } while ((Data & LSR_RXDA) == 0); + + *Buffer++ = IoRead8 ((UINT16) gUartBase); + } + + return Result; +} + +/** + Polls a serial device to see if there is any data waiting to be read. + + Polls a serial device to see if there is any data waiting to be read. + If there is data waiting to be read from the serial device, then TRUE is returned. + If there is no data waiting to be read from the serial device, then FALSE is returned. + + @retval TRUE Data is waiting to be read from the serial device. + @retval FALSE There is no data waiting to be read from the serial device. + +**/ +BOOLEAN +EFIAPI +SerialPortPoll ( + VOID + ) +{ + UINT8 Data; + + // + // Read the serial port status. + // + Data = IoRead8 ((UINT16) gUartBase + LSR_OFFSET); + + return (BOOLEAN) ((Data & LSR_RXDA) != 0); +} + +/** + Sets the control bits on a serial device. + + @param Control Sets the bits of Control that are settable. + + @retval RETURN_SUCCESS The new control bits were set on the serial device. + @retval RETURN_UNSUPPORTED The serial device does not support this operation. + @retval RETURN_DEVICE_ERROR The serial device is not functioning correctly. + +**/ +RETURN_STATUS +EFIAPI +SerialPortSetControl ( + IN UINT32 Control + ) +{ + UINT8 Mcr; + + // + // First determine the parameter is invalid. + // + if ((Control & (~(EFI_SERIAL_REQUEST_TO_SEND | EFI_SERIAL_DATA_TERMINAL_READY))) != 0) { + return RETURN_UNSUPPORTED; + } + + // + // Read the Modem Control Register. + // + Mcr = IoRead8 ((UINT16) gUartBase + MCR_OFFSET); + Mcr &= (~(MCR_DTRC | MCR_RTS)); + + if ((Control & EFI_SERIAL_DATA_TERMINAL_READY) == EFI_SERIAL_DATA_TERMINAL_READY) { + Mcr |= MCR_DTRC; + } + + if ((Control & EFI_SERIAL_REQUEST_TO_SEND) == EFI_SERIAL_REQUEST_TO_SEND) { + Mcr |= MCR_RTS; + } + + // + // Write the Modem Control Register. + // + IoWrite8 ((UINT16) gUartBase + MCR_OFFSET, Mcr); + + return RETURN_SUCCESS; +} + +/** + Retrieve the status of the control bits on a serial device. + + @param Control A pointer to return the current control signals from the serial device. + + @retval RETURN_SUCCESS The control bits were read from the serial device. + @retval RETURN_UNSUPPORTED The serial device does not support this operation. + @retval RETURN_DEVICE_ERROR The serial device is not functioning correctly. + +**/ +RETURN_STATUS +EFIAPI +SerialPortGetControl ( + OUT UINT32 *Control + ) +{ + UINT8 Msr; + UINT8 Mcr; + UINT8 Lsr; + + *Control = 0; + + // + // Read the Modem Status Register. + // + Msr = IoRead8 ((UINT16) gUartBase + MSR_OFFSET); + + if ((Msr & MSR_CTS) == MSR_CTS) { + *Control |= EFI_SERIAL_CLEAR_TO_SEND; + } + + if ((Msr & MSR_DSR) == MSR_DSR) { + *Control |= EFI_SERIAL_DATA_SET_READY; + } + + if ((Msr & MSR_RI) == MSR_RI) { + *Control |= EFI_SERIAL_RING_INDICATE; + } + + if ((Msr & MSR_DCD) == MSR_DCD) { + *Control |= EFI_SERIAL_CARRIER_DETECT; + } + + // + // Read the Modem Control Register. + // + Mcr = IoRead8 ((UINT16) gUartBase + MCR_OFFSET); + + if ((Mcr & MCR_DTRC) == MCR_DTRC) { + *Control |= EFI_SERIAL_DATA_TERMINAL_READY; + } + + if ((Mcr & MCR_RTS) == MCR_RTS) { + *Control |= EFI_SERIAL_REQUEST_TO_SEND; + } + + // + // Read the Line Status Register. + // + Lsr = IoRead8 ((UINT16) gUartBase + LSR_OFFSET); + + if ((Lsr & LSR_TXRDY) == LSR_TXRDY) { + *Control |= EFI_SERIAL_OUTPUT_BUFFER_EMPTY; + } + + if ((Lsr & LSR_RXDA) == 0) { + *Control |= EFI_SERIAL_INPUT_BUFFER_EMPTY; + } + + return RETURN_SUCCESS; +} + +/** + Sets the baud rate, receive FIFO depth, transmit/receive time out, parity, + data bits, and stop bits on a serial device. + + @param BaudRate The requested baud rate. A BaudRate value of 0 will use the + device's default interface speed. + On output, the value actually set. + @param ReceiveFifoDepth The requested depth of the FIFO on the receive side of the + serial interface. A ReceiveFifoDepth value of 0 will use + the device's default FIFO depth. + On output, the value actually set. + @param Timeout The requested time out for a single character in microseconds. + This timeout applies to both the transmit and receive side of the + interface. A Timeout value of 0 will use the device's default time + out value. + On output, the value actually set. + @param Parity The type of parity to use on this serial device. A Parity value of + DefaultParity will use the device's default parity value. + On output, the value actually set. + @param DataBits The number of data bits to use on the serial device. A DataBits + value of 0 will use the device's default data bit setting. + On output, the value actually set. + @param StopBits The number of stop bits to use on this serial device. A StopBits + value of DefaultStopBits will use the device's default number of + stop bits. + On output, the value actually set. + + @retval RETURN_SUCCESS The new attributes were set on the serial device. + @retval RETURN_UNSUPPORTED The serial device does not support this operation. + @retval RETURN_INVALID_PARAMETER One or more of the attributes has an unsupported value. + @retval RETURN_DEVICE_ERROR The serial device is not functioning correctly. + +**/ +RETURN_STATUS +EFIAPI +SerialPortSetAttributes ( + IN OUT UINT64 *BaudRate, + IN OUT UINT32 *ReceiveFifoDepth, + IN OUT UINT32 *Timeout, + IN OUT EFI_PARITY_TYPE *Parity, + IN OUT UINT8 *DataBits, + IN OUT EFI_STOP_BITS_TYPE *StopBits + ) +{ + UINTN Divisor; + UINT8 OutputData; + UINT8 LcrData; + UINT8 LcrParity; + UINT8 LcrStop; + + // + // Check for default settings and fill in actual values. + // + if (*BaudRate == 0) { + *BaudRate = gBps; + } + + if (*DataBits == 0) { + *DataBits = gData; + } + + if (*Parity == DefaultParity) { + *Parity = NoParity; + } + + if (*StopBits == DefaultStopBits) { + *StopBits = OneStopBit; + } + + if ((*DataBits < 5) || (*DataBits > 8)) { + return RETURN_INVALID_PARAMETER; + } + + // + // Map 5..8 to 0..3 + // + LcrData = (UINT8) (*DataBits - (UINT8) 5); + + switch (*Parity) { + case NoParity: + LcrParity = 0; + break; + + case EvenParity: + LcrParity = 3; + break; + + case OddParity: + LcrParity = 1; + break; + + case SpaceParity: + LcrParity = 7; + break; + + case MarkParity: + LcrParity = 5; + break; + + default: + return RETURN_INVALID_PARAMETER; + } + + switch (*StopBits) { + case OneStopBit: + LcrStop = 0; + break; + + case OneFiveStopBits: + case TwoStopBits: + LcrStop = 1; + break; + + default: + return RETURN_INVALID_PARAMETER; + } + + // + // Calculate divisor for baud generator + // + Divisor = 115200 / (UINTN) *BaudRate; + + // + // Set communications format + // + OutputData = (UINT8) ((DLAB << 7) | (gBreakSet << 6) | (LcrParity << 3) | (LcrStop << 2) | LcrData); + IoWrite8 (gUartBase + LCR_OFFSET, OutputData); + + // + // Configure baud rate + // + IoWrite8 (gUartBase + BAUD_HIGH_OFFSET, (UINT8) (Divisor >> 8)); + IoWrite8 (gUartBase + BAUD_LOW_OFFSET, (UINT8) (Divisor & 0xff)); + + // + // Switch back to bank 0 + // + OutputData = (UINT8) ((gBreakSet << 6) | (LcrParity << 3) | (LcrStop << 2) | LcrData); + IoWrite8 (gUartBase + LCR_OFFSET, OutputData); + + return RETURN_SUCCESS; +} + |