612 lines
18 KiB
Diff
612 lines
18 KiB
Diff
From d9b5815d797260ca8c8af1f8cca19e85c8c32a09 Mon Sep 17 00:00:00 2001
|
|
From: =?UTF-8?q?Mario=20B=C4=83l=C4=83nic=C4=83?=
|
|
<mariobalanica02@gmail.com>
|
|
Date: Fri, 29 Dec 2023 23:29:47 +0200
|
|
Subject: [PATCH 09/16] Platform/RPi5: Add real-time clock support
|
|
MIME-Version: 1.0
|
|
Content-Type: text/plain; charset=UTF-8
|
|
Content-Transfer-Encoding: 8bit
|
|
|
|
Working get/set time and wake up alarm within UEFI.
|
|
|
|
Signed-off-by: Mario Bălănică <mariobalanica02@gmail.com>
|
|
---
|
|
.../Drivers/RpiFirmwareDxe/RpiFirmwareDxe.c | 110 ++++++-
|
|
.../Include/IndustryStandard/RpiMbox.h | 2 +
|
|
.../Include/Protocol/RpiFirmware.h | 28 ++
|
|
.../RaspberryPi/Library/RpiRtcLib/RpiRtcLib.c | 305 ++++++++++++++++++
|
|
.../Library/RpiRtcLib/RpiRtcLib.inf | 42 +++
|
|
Platform/RaspberryPi/RPi5/RPi5.dsc | 2 +-
|
|
6 files changed, 487 insertions(+), 2 deletions(-)
|
|
create mode 100644 Platform/RaspberryPi/Library/RpiRtcLib/RpiRtcLib.c
|
|
create mode 100644 Platform/RaspberryPi/Library/RpiRtcLib/RpiRtcLib.inf
|
|
|
|
diff --git a/Platform/RaspberryPi/Drivers/RpiFirmwareDxe/RpiFirmwareDxe.c b/Platform/RaspberryPi/Drivers/RpiFirmwareDxe/RpiFirmwareDxe.c
|
|
index 9077f077..b432e828 100644
|
|
--- a/Platform/RaspberryPi/Drivers/RpiFirmwareDxe/RpiFirmwareDxe.c
|
|
+++ b/Platform/RaspberryPi/Drivers/RpiFirmwareDxe/RpiFirmwareDxe.c
|
|
@@ -1,5 +1,6 @@
|
|
/** @file
|
|
*
|
|
+ * Copyright (c) 2023, Mario Bălănică <mariobalanica02@gmail.com>
|
|
* Copyright (c) 2020, Pete Batard <pete@akeo.ie>
|
|
* Copyright (c) 2019, ARM Limited. All rights reserved.
|
|
* Copyright (c) 2017-2020, Andrei Warkentin <andrey.warkentin@gmail.com>
|
|
@@ -1332,6 +1333,111 @@ RpiFirmwareNotifyGpioSetCfg (
|
|
return Status;
|
|
}
|
|
|
|
+
|
|
+#pragma pack()
|
|
+typedef struct {
|
|
+ UINT32 Register;
|
|
+ UINT32 Value;
|
|
+} RPI_FW_RTC_TAG;
|
|
+
|
|
+typedef struct {
|
|
+ RPI_FW_BUFFER_HEAD BufferHead;
|
|
+ RPI_FW_TAG_HEAD TagHead;
|
|
+ RPI_FW_RTC_TAG TagBody;
|
|
+ UINT32 EndTag;
|
|
+} RPI_FW_RTC_CMD;
|
|
+#pragma pack()
|
|
+
|
|
+STATIC
|
|
+EFI_STATUS
|
|
+EFIAPI
|
|
+RpiFirmwareGetRtc (
|
|
+ IN RASPBERRY_PI_RTC_REGISTER Register,
|
|
+ OUT UINT32 *Value
|
|
+ )
|
|
+{
|
|
+ RPI_FW_RTC_CMD *Cmd;
|
|
+ EFI_STATUS Status;
|
|
+ UINT32 Result;
|
|
+
|
|
+ if (!AcquireSpinLockOrFail (&mMailboxLock)) {
|
|
+ DEBUG ((DEBUG_ERROR, "%a: failed to acquire spinlock\n", __FUNCTION__));
|
|
+ return EFI_DEVICE_ERROR;
|
|
+ }
|
|
+
|
|
+ Cmd = mDmaBuffer;
|
|
+ ZeroMem (Cmd, sizeof (*Cmd));
|
|
+
|
|
+ Cmd->BufferHead.BufferSize = sizeof (*Cmd);
|
|
+ Cmd->BufferHead.Response = 0;
|
|
+ Cmd->TagHead.TagId = RPI_MBOX_GET_RTC_REG;
|
|
+ Cmd->TagHead.TagSize = sizeof (Cmd->TagBody);
|
|
+ Cmd->TagHead.TagValueSize = 0;
|
|
+ Cmd->TagBody.Register = Register;
|
|
+ Cmd->TagBody.Value = 0;
|
|
+ Cmd->EndTag = 0;
|
|
+
|
|
+ Status = MailboxTransaction (Cmd->BufferHead.BufferSize, RPI_MBOX_VC_CHANNEL, &Result);
|
|
+
|
|
+ if (EFI_ERROR (Status) ||
|
|
+ Cmd->BufferHead.Response != RPI_MBOX_RESP_SUCCESS) {
|
|
+ DEBUG ((DEBUG_ERROR,
|
|
+ "%a: mailbox transaction error: Status == %r, Response == 0x%x\n",
|
|
+ __FUNCTION__, Status, Cmd->BufferHead.Response));
|
|
+ Status = EFI_DEVICE_ERROR;
|
|
+ } else {
|
|
+ *Value = Cmd->TagBody.Value;
|
|
+ }
|
|
+
|
|
+ ReleaseSpinLock (&mMailboxLock);
|
|
+
|
|
+ return Status;
|
|
+}
|
|
+
|
|
+STATIC
|
|
+EFI_STATUS
|
|
+EFIAPI
|
|
+RpiFirmwareSetRtc (
|
|
+ IN RASPBERRY_PI_RTC_REGISTER Register,
|
|
+ IN UINT32 Value
|
|
+ )
|
|
+{
|
|
+ RPI_FW_RTC_CMD *Cmd;
|
|
+ EFI_STATUS Status;
|
|
+ UINT32 Result;
|
|
+
|
|
+ if (!AcquireSpinLockOrFail (&mMailboxLock)) {
|
|
+ DEBUG ((DEBUG_ERROR, "%a: failed to acquire spinlock\n", __FUNCTION__));
|
|
+ return EFI_DEVICE_ERROR;
|
|
+ }
|
|
+
|
|
+ Cmd = mDmaBuffer;
|
|
+ ZeroMem (Cmd, sizeof (*Cmd));
|
|
+
|
|
+ Cmd->BufferHead.BufferSize = sizeof (*Cmd);
|
|
+ Cmd->BufferHead.Response = 0;
|
|
+ Cmd->TagHead.TagId = RPI_MBOX_SET_RTC_REG;
|
|
+ Cmd->TagHead.TagSize = sizeof (Cmd->TagBody);
|
|
+ Cmd->TagHead.TagValueSize = 0;
|
|
+ Cmd->TagBody.Register = Register;
|
|
+ Cmd->TagBody.Value = Value;
|
|
+ Cmd->EndTag = 0;
|
|
+
|
|
+ Status = MailboxTransaction (Cmd->BufferHead.BufferSize, RPI_MBOX_VC_CHANNEL, &Result);
|
|
+
|
|
+ if (EFI_ERROR (Status) ||
|
|
+ Cmd->BufferHead.Response != RPI_MBOX_RESP_SUCCESS) {
|
|
+ DEBUG ((DEBUG_ERROR,
|
|
+ "%a: mailbox transaction error: Status == %r, Response == 0x%x\n",
|
|
+ __FUNCTION__, Status, Cmd->BufferHead.Response));
|
|
+ Status = EFI_DEVICE_ERROR;
|
|
+ }
|
|
+
|
|
+ ReleaseSpinLock (&mMailboxLock);
|
|
+
|
|
+ return Status;
|
|
+}
|
|
+
|
|
STATIC RASPBERRY_PI_FIRMWARE_PROTOCOL mRpiFirmwareProtocol = {
|
|
RpiFirmwareSetPowerState,
|
|
RpiFirmwareGetMacAddress,
|
|
@@ -1352,7 +1458,9 @@ STATIC RASPBERRY_PI_FIRMWARE_PROTOCOL mRpiFirmwareProtocol = {
|
|
RpiFirmwareNotifyXhciReset,
|
|
RpiFirmwareGetCurrentClockState,
|
|
RpiFirmwareSetClockState,
|
|
- RpiFirmwareNotifyGpioSetCfg
|
|
+ RpiFirmwareNotifyGpioSetCfg,
|
|
+ RpiFirmwareGetRtc,
|
|
+ RpiFirmwareSetRtc,
|
|
};
|
|
|
|
/**
|
|
diff --git a/Platform/RaspberryPi/Include/IndustryStandard/RpiMbox.h b/Platform/RaspberryPi/Include/IndustryStandard/RpiMbox.h
|
|
index 551c2b82..916b7442 100644
|
|
--- a/Platform/RaspberryPi/Include/IndustryStandard/RpiMbox.h
|
|
+++ b/Platform/RaspberryPi/Include/IndustryStandard/RpiMbox.h
|
|
@@ -93,6 +93,7 @@
|
|
#define RPI_MBOX_GET_POE_HAT_VAL 0x00030049
|
|
#define RPI_MBOX_SET_POE_HAT_VAL 0x00030050
|
|
#define RPI_MBOX_NOTIFY_XHCI_RESET 0x00030058
|
|
+#define RPI_MBOX_GET_RTC_REG 0x00030087
|
|
|
|
#define RPI_MBOX_SET_CLOCK_STATE 0x00038001
|
|
#define RPI_MBOX_SET_CLOCK_RATE 0x00038002
|
|
@@ -104,6 +105,7 @@
|
|
#define RPI_MBOX_SET_SDHOST_CLOCK 0x00038042
|
|
#define RPI_MBOX_SET_GPIO_CONFIG 0x00038043
|
|
#define RPI_MBOX_SET_PERIPH_REG 0x00038045
|
|
+#define RPI_MBOX_SET_RTC_REG 0x00038087
|
|
|
|
#define RPI_MBOX_ALLOC_FB 0x00040001
|
|
#define RPI_MBOX_FB_BLANK 0x00040002
|
|
diff --git a/Platform/RaspberryPi/Include/Protocol/RpiFirmware.h b/Platform/RaspberryPi/Include/Protocol/RpiFirmware.h
|
|
index 86bf1687..92ab7f84 100644
|
|
--- a/Platform/RaspberryPi/Include/Protocol/RpiFirmware.h
|
|
+++ b/Platform/RaspberryPi/Include/Protocol/RpiFirmware.h
|
|
@@ -1,5 +1,6 @@
|
|
/** @file
|
|
*
|
|
+ * Copyright (c) 2023, Mario Bălănică <mariobalanica02@gmail.com>
|
|
* Copyright (c) 2019, ARM Limited. All rights reserved.
|
|
* Copyright (c) 2017 - 2020, Andrei Warkentin <andrey.warkentin@gmail.com>
|
|
* Copyright (c) 2016, Linaro Limited. All rights reserved.
|
|
@@ -14,6 +15,17 @@
|
|
#define RASPBERRY_PI_FIRMWARE_PROTOL_GUID \
|
|
{ 0x0ACA9535, 0x7AD0, 0x4286, { 0xB0, 0x2E, 0x87, 0xFA, 0x7E, 0x2A, 0x57, 0x11 } }
|
|
|
|
+typedef enum {
|
|
+ RpiRtcTime = 0,
|
|
+ RpiRtcAlarm,
|
|
+ RpiRtcAlarmPending,
|
|
+ RpiRtcAlarmEnable,
|
|
+ RpiRtcBatteryChargeVoltage,
|
|
+ RpiRtcBatteryChargeVoltageMin,
|
|
+ RpiRtcBatteryChargeVoltageMax,
|
|
+ RpiRtcBatteryVoltage,
|
|
+} RASPBERRY_PI_RTC_REGISTER;
|
|
+
|
|
typedef
|
|
EFI_STATUS
|
|
(EFIAPI *SET_POWER_STATE) (
|
|
@@ -141,6 +153,20 @@ EFI_STATUS
|
|
UINTN State
|
|
);
|
|
|
|
+typedef
|
|
+EFI_STATUS
|
|
+(EFIAPI *GET_RTC) (
|
|
+ IN RASPBERRY_PI_RTC_REGISTER Register,
|
|
+ OUT UINT32 *Value
|
|
+ );
|
|
+
|
|
+typedef
|
|
+EFI_STATUS
|
|
+(EFIAPI *SET_RTC) (
|
|
+ IN RASPBERRY_PI_RTC_REGISTER Register,
|
|
+ IN UINT32 Value
|
|
+ );
|
|
+
|
|
typedef struct {
|
|
SET_POWER_STATE SetPowerState;
|
|
GET_MAC_ADDRESS GetMacAddress;
|
|
@@ -162,6 +188,8 @@ typedef struct {
|
|
GET_CLOCK_STATE GetClockState;
|
|
SET_CLOCK_STATE SetClockState;
|
|
GPIO_SET_CFG SetGpioConfig;
|
|
+ GET_RTC GetRtc;
|
|
+ SET_RTC SetRtc;
|
|
} RASPBERRY_PI_FIRMWARE_PROTOCOL;
|
|
|
|
extern EFI_GUID gRaspberryPiFirmwareProtocolGuid;
|
|
diff --git a/Platform/RaspberryPi/Library/RpiRtcLib/RpiRtcLib.c b/Platform/RaspberryPi/Library/RpiRtcLib/RpiRtcLib.c
|
|
new file mode 100644
|
|
index 00000000..298b3678
|
|
--- /dev/null
|
|
+++ b/Platform/RaspberryPi/Library/RpiRtcLib/RpiRtcLib.c
|
|
@@ -0,0 +1,305 @@
|
|
+/** @file
|
|
+ *
|
|
+ * Copyright (c) 2023, Mario Bălănică <mariobalanica02@gmail.com>
|
|
+ *
|
|
+ * SPDX-License-Identifier: BSD-2-Clause-Patent
|
|
+ *
|
|
+ **/
|
|
+
|
|
+#include <PiDxe.h>
|
|
+
|
|
+#include <Library/DebugLib.h>
|
|
+#include <Library/RealTimeClockLib.h>
|
|
+#include <Library/TimeBaseLib.h>
|
|
+#include <Library/UefiBootServicesTableLib.h>
|
|
+#include <Library/UefiRuntimeLib.h>
|
|
+
|
|
+#include <Protocol/RpiFirmware.h>
|
|
+
|
|
+STATIC RASPBERRY_PI_FIRMWARE_PROTOCOL *mFwProtocol;
|
|
+
|
|
+STATIC
|
|
+VOID
|
|
+EFIAPI
|
|
+OffsetTimeZoneEpoch (
|
|
+ IN EFI_TIME *Time,
|
|
+ IN OUT UINT32 *EpochSeconds,
|
|
+ IN BOOLEAN Add
|
|
+ )
|
|
+{
|
|
+ //
|
|
+ // Adjust for the correct time zone
|
|
+ // The timezone setting also reflects the DST setting of the clock
|
|
+ //
|
|
+ if (Time->TimeZone != EFI_UNSPECIFIED_TIMEZONE) {
|
|
+ *EpochSeconds += (Add ? 1 : -1) * Time->TimeZone * SEC_PER_MIN;
|
|
+ } else if ((Time->Daylight & EFI_TIME_IN_DAYLIGHT) == EFI_TIME_IN_DAYLIGHT) {
|
|
+ // Convert to adjusted time, i.e. spring forwards one hour
|
|
+ *EpochSeconds += (Add ? 1 : -1) * SEC_PER_HOUR;
|
|
+ }
|
|
+}
|
|
+
|
|
+/**
|
|
+ Returns the current time and date information, and the time-keeping capabilities
|
|
+ of the hardware platform.
|
|
+
|
|
+ @param Time A pointer to storage to receive a snapshot of the current time.
|
|
+ @param Capabilities An optional pointer to a buffer to receive the real time clock
|
|
+ device's capabilities.
|
|
+
|
|
+ @retval EFI_SUCCESS The operation completed successfully.
|
|
+ @retval EFI_INVALID_PARAMETER Time is NULL.
|
|
+ @retval EFI_DEVICE_ERROR The time could not be retrieved due to hardware error.
|
|
+ @retval EFI_SECURITY_VIOLATION The time could not be retrieved due to an authentication failure.
|
|
+
|
|
+**/
|
|
+EFI_STATUS
|
|
+EFIAPI
|
|
+LibGetTime (
|
|
+ OUT EFI_TIME *Time,
|
|
+ OUT EFI_TIME_CAPABILITIES *Capabilities
|
|
+ )
|
|
+{
|
|
+ EFI_STATUS Status;
|
|
+ UINT32 EpochSeconds;
|
|
+
|
|
+ if (Time == NULL) {
|
|
+ return EFI_INVALID_PARAMETER;
|
|
+ }
|
|
+
|
|
+ Status = mFwProtocol->GetRtc (RpiRtcTime, &EpochSeconds);
|
|
+ if (EFI_ERROR (Status)) {
|
|
+ return Status;
|
|
+ }
|
|
+
|
|
+ OffsetTimeZoneEpoch (Time, &EpochSeconds, TRUE);
|
|
+
|
|
+ EpochToEfiTime (EpochSeconds, Time);
|
|
+
|
|
+ return EFI_SUCCESS;
|
|
+}
|
|
+
|
|
+/**
|
|
+ Sets the current local time and date information.
|
|
+
|
|
+ @param Time A pointer to the current time.
|
|
+
|
|
+ @retval EFI_SUCCESS The operation completed successfully.
|
|
+ @retval EFI_INVALID_PARAMETER A time field is out of range.
|
|
+ @retval EFI_DEVICE_ERROR The time could not be set due to hardware error.
|
|
+
|
|
+**/
|
|
+EFI_STATUS
|
|
+EFIAPI
|
|
+LibSetTime (
|
|
+ IN EFI_TIME *Time
|
|
+ )
|
|
+{
|
|
+ EFI_STATUS Status;
|
|
+ UINT32 EpochSeconds;
|
|
+
|
|
+ if (Time == NULL || !IsTimeValid (Time)) {
|
|
+ return EFI_UNSUPPORTED;
|
|
+ }
|
|
+
|
|
+ EpochSeconds = (UINT32)EfiTimeToEpoch (Time);
|
|
+
|
|
+ OffsetTimeZoneEpoch (Time, &EpochSeconds, FALSE);
|
|
+
|
|
+ Status = mFwProtocol->SetRtc (RpiRtcTime, EpochSeconds);
|
|
+ if (EFI_ERROR (Status)) {
|
|
+ return Status;
|
|
+ }
|
|
+
|
|
+ return EFI_SUCCESS;
|
|
+}
|
|
+
|
|
+/**
|
|
+ Returns the current wakeup alarm clock setting.
|
|
+
|
|
+ @param Enabled Indicates if the alarm is currently enabled or disabled.
|
|
+ @param Pending Indicates if the alarm signal is pending and requires acknowledgement.
|
|
+ @param Time The current alarm setting.
|
|
+
|
|
+ @retval EFI_SUCCESS The alarm settings were returned.
|
|
+ @retval EFI_INVALID_PARAMETER Any parameter is NULL.
|
|
+ @retval EFI_DEVICE_ERROR The wakeup time could not be retrieved due to a hardware error.
|
|
+
|
|
+**/
|
|
+EFI_STATUS
|
|
+EFIAPI
|
|
+LibGetWakeupTime (
|
|
+ OUT BOOLEAN *Enabled,
|
|
+ OUT BOOLEAN *Pending,
|
|
+ OUT EFI_TIME *Time
|
|
+ )
|
|
+{
|
|
+ EFI_STATUS Status;
|
|
+ UINT32 EpochSeconds;
|
|
+ UINT32 EnableVal;
|
|
+ UINT32 PendingVal;
|
|
+
|
|
+ if (Time == NULL || Enabled == NULL || Pending == NULL) {
|
|
+ return EFI_INVALID_PARAMETER;
|
|
+ }
|
|
+
|
|
+ Status = mFwProtocol->GetRtc (RpiRtcAlarmEnable, &EnableVal);
|
|
+ if (EFI_ERROR (Status)) {
|
|
+ return Status;
|
|
+ }
|
|
+
|
|
+ Status = mFwProtocol->GetRtc (RpiRtcAlarmPending, &PendingVal);
|
|
+ if (EFI_ERROR (Status)) {
|
|
+ return Status;
|
|
+ }
|
|
+
|
|
+ *Enabled = EnableVal;
|
|
+ *Pending = PendingVal;
|
|
+
|
|
+ if (*Pending) {
|
|
+ // Acknowledge alarm
|
|
+ Status = mFwProtocol->SetRtc (RpiRtcAlarmPending, TRUE);
|
|
+ if (EFI_ERROR (Status)) {
|
|
+ return Status;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ Status = mFwProtocol->GetRtc (RpiRtcAlarm, &EpochSeconds);
|
|
+ if (EFI_ERROR (Status)) {
|
|
+ return Status;
|
|
+ }
|
|
+
|
|
+ OffsetTimeZoneEpoch (Time, &EpochSeconds, TRUE);
|
|
+
|
|
+ EpochToEfiTime (EpochSeconds, Time);
|
|
+
|
|
+ return EFI_SUCCESS;
|
|
+}
|
|
+
|
|
+/**
|
|
+ Sets the system wakeup alarm clock time.
|
|
+
|
|
+ @param Enabled Enable or disable the wakeup alarm.
|
|
+ @param Time If Enable is TRUE, the time to set the wakeup alarm for.
|
|
+
|
|
+ @retval EFI_SUCCESS If Enable is TRUE, then the wakeup alarm was enabled. If
|
|
+ Enable is FALSE, then the wakeup alarm was disabled.
|
|
+ @retval EFI_INVALID_PARAMETER A time field is out of range.
|
|
+ @retval EFI_DEVICE_ERROR The wakeup time could not be set due to a hardware error.
|
|
+ @retval EFI_UNSUPPORTED A wakeup timer is not supported on this platform.
|
|
+
|
|
+**/
|
|
+EFI_STATUS
|
|
+EFIAPI
|
|
+LibSetWakeupTime (
|
|
+ IN BOOLEAN Enabled,
|
|
+ OUT EFI_TIME *Time
|
|
+ )
|
|
+{
|
|
+ EFI_STATUS Status;
|
|
+ UINT32 EpochSeconds;
|
|
+
|
|
+ if (Enabled) {
|
|
+ if (Time == NULL || !IsTimeValid (Time)) {
|
|
+ return EFI_INVALID_PARAMETER;
|
|
+ }
|
|
+
|
|
+ EpochSeconds = (UINT32)EfiTimeToEpoch (Time);
|
|
+
|
|
+ OffsetTimeZoneEpoch (Time, &EpochSeconds, FALSE);
|
|
+
|
|
+ Status = mFwProtocol->SetRtc (RpiRtcAlarm, EpochSeconds);
|
|
+ if (EFI_ERROR (Status)) {
|
|
+ return Status;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ Status = mFwProtocol->SetRtc (RpiRtcAlarmEnable, Enabled);
|
|
+ if (EFI_ERROR (Status)) {
|
|
+ return Status;
|
|
+ }
|
|
+
|
|
+ return EFI_SUCCESS;
|
|
+}
|
|
+
|
|
+/**
|
|
+ Fixup internal data so that EFI can be call in virtual mode.
|
|
+ Call the passed in Child Notify event and convert any pointers in
|
|
+ lib to virtual mode.
|
|
+
|
|
+ @param[in] Event The Event that is being processed
|
|
+ @param[in] Context Event Context
|
|
+
|
|
+**/
|
|
+STATIC
|
|
+VOID
|
|
+EFIAPI
|
|
+VirtualAddressChangeNotify (
|
|
+ IN EFI_EVENT Event,
|
|
+ IN VOID *Context
|
|
+ )
|
|
+{
|
|
+ EfiConvertPointer (0x0, (VOID **)&mFwProtocol);
|
|
+}
|
|
+
|
|
+/**
|
|
+ This is the declaration of an EFI image entry point. This can be the entry point to an application
|
|
+ written to this specification, an EFI boot service driver, or an EFI runtime driver.
|
|
+
|
|
+ @param ImageHandle Handle that identifies the loaded image.
|
|
+ @param SystemTable System Table for this image.
|
|
+
|
|
+ @retval EFI_SUCCESS The operation completed successfully.
|
|
+
|
|
+**/
|
|
+EFI_STATUS
|
|
+EFIAPI
|
|
+LibRtcInitialize (
|
|
+ IN EFI_HANDLE ImageHandle,
|
|
+ IN EFI_SYSTEM_TABLE *SystemTable
|
|
+ )
|
|
+{
|
|
+ EFI_STATUS Status;
|
|
+ EFI_TIME Time;
|
|
+ EFI_EVENT VirtualAddressChangeEvent;
|
|
+
|
|
+ Status = gBS->LocateProtocol (
|
|
+ &gRaspberryPiFirmwareProtocolGuid,
|
|
+ NULL,
|
|
+ (VOID **)&mFwProtocol);
|
|
+ ASSERT_EFI_ERROR (Status);
|
|
+ if (EFI_ERROR (Status)) {
|
|
+ return Status;
|
|
+ }
|
|
+
|
|
+ Status = gBS->CreateEventEx (
|
|
+ EVT_NOTIFY_SIGNAL,
|
|
+ TPL_NOTIFY,
|
|
+ VirtualAddressChangeNotify,
|
|
+ NULL,
|
|
+ &gEfiEventVirtualAddressChangeGuid,
|
|
+ &VirtualAddressChangeEvent);
|
|
+ ASSERT_EFI_ERROR (Status);
|
|
+ if (EFI_ERROR (Status)) {
|
|
+ return Status;
|
|
+ }
|
|
+
|
|
+ //
|
|
+ // Initial RTC time starts off at Epoch = 0, which is out
|
|
+ // of UEFI's bounds. Update it to the firmware build time.
|
|
+ //
|
|
+ Status = LibGetTime (&Time, NULL);
|
|
+ if (EFI_ERROR(Status)) {
|
|
+ return Status;
|
|
+ }
|
|
+
|
|
+ if (!IsTimeValid (&Time)) {
|
|
+ EpochToEfiTime (BUILD_EPOCH, &Time);
|
|
+ Status = LibSetTime (&Time);
|
|
+ if (EFI_ERROR(Status)) {
|
|
+ return Status;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ return EFI_SUCCESS;
|
|
+}
|
|
diff --git a/Platform/RaspberryPi/Library/RpiRtcLib/RpiRtcLib.inf b/Platform/RaspberryPi/Library/RpiRtcLib/RpiRtcLib.inf
|
|
new file mode 100644
|
|
index 00000000..f271f39c
|
|
--- /dev/null
|
|
+++ b/Platform/RaspberryPi/Library/RpiRtcLib/RpiRtcLib.inf
|
|
@@ -0,0 +1,42 @@
|
|
+#/** @file
|
|
+#
|
|
+# Copyright (c) 2023, Mario Bălănică <mariobalanica02@gmail.com>
|
|
+#
|
|
+# SPDX-License-Identifier: BSD-2-Clause-Patent
|
|
+#
|
|
+#**/
|
|
+
|
|
+[Defines]
|
|
+ INF_VERSION = 0x0001001A
|
|
+ BASE_NAME = RpiRtcLib
|
|
+ FILE_GUID = 2c823916-13b7-48f3-bb6d-a8cf438b91fd
|
|
+ MODULE_TYPE = BASE
|
|
+ VERSION_STRING = 1.0
|
|
+ LIBRARY_CLASS = RealTimeClockLib
|
|
+
|
|
+[Sources.common]
|
|
+ RpiRtcLib.c
|
|
+
|
|
+[Packages]
|
|
+ EmbeddedPkg/EmbeddedPkg.dec
|
|
+ MdePkg/MdePkg.dec
|
|
+ Platform/RaspberryPi/RaspberryPi.dec
|
|
+
|
|
+[LibraryClasses]
|
|
+ DebugLib
|
|
+ TimeBaseLib
|
|
+ UefiBootServicesTableLib
|
|
+ UefiRuntimeLib
|
|
+
|
|
+[Guids]
|
|
+ gEfiEventVirtualAddressChangeGuid
|
|
+
|
|
+[Protocols]
|
|
+ gRaspberryPiFirmwareProtocolGuid ## CONSUMES
|
|
+
|
|
+[Depex]
|
|
+ gRaspberryPiFirmwareProtocolGuid
|
|
+
|
|
+# Current usage of this library expects GCC in a UNIX-like shell environment with the date command
|
|
+[BuildOptions]
|
|
+ GCC:*_*_*_CC_FLAGS = -DBUILD_EPOCH=`date +%s`
|
|
diff --git a/Platform/RaspberryPi/RPi5/RPi5.dsc b/Platform/RaspberryPi/RPi5/RPi5.dsc
|
|
index f8e08de2..f2a1992e 100644
|
|
--- a/Platform/RaspberryPi/RPi5/RPi5.dsc
|
|
+++ b/Platform/RaspberryPi/RPi5/RPi5.dsc
|
|
@@ -547,7 +547,7 @@
|
|
EmbeddedPkg/ResetRuntimeDxe/ResetRuntimeDxe.inf
|
|
EmbeddedPkg/RealTimeClockRuntimeDxe/RealTimeClockRuntimeDxe.inf {
|
|
<LibraryClasses>
|
|
- RealTimeClockLib|EmbeddedPkg/Library/VirtualRealTimeClockLib/VirtualRealTimeClockLib.inf
|
|
+ RealTimeClockLib|Platform/RaspberryPi/Library/RpiRtcLib/RpiRtcLib.inf
|
|
}
|
|
EmbeddedPkg/MetronomeDxe/MetronomeDxe.inf
|
|
|
|
--
|
|
2.51.2
|
|
|