+/** @file\r
+ Adjust Default System Time.\r
+ \r
+ Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>\r
+ \r
+ This program and the accompanying materials are licensed and made available under\r
+ the terms and conditions of the BSD License that accompanies this distribution. \r
+ The full text of the license may be found at \r
+ http://opensource.org/licenses/bsd-license.php. \r
+ \r
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r
+ \r
+--*/\r
+\r
+#include <PlatformDxe.h>\r
+\r
+//\r
+// Date and time initial values.\r
+// They are used if the RTC values are invalid during driver initialization\r
+//\r
+#define RTC_INIT_SECOND 0\r
+#define RTC_INIT_MINUTE 0\r
+#define RTC_INIT_HOUR 0\r
+ \r
+CHAR16 mBiosReleaseDate[20]; \r
+ \r
+/**\r
+ Convert a single character to number.\r
+ It assumes the input Char is in the scope of L'0' ~ L'9' and L'A' ~ L'F'\r
+ \r
+ @param Char The input char which need to change to a hex number.\r
+ \r
+**/\r
+UINTN\r
+CharToUint (\r
+ IN CHAR16 Char\r
+ )\r
+{\r
+ if ((Char >= L'0') && (Char <= L'9')) {\r
+ return (UINTN) (Char - L'0');\r
+ }\r
+\r
+ if ((Char >= L'A') && (Char <= L'F')) {\r
+ return (UINTN) (Char - L'A' + 0xA);\r
+ }\r
+\r
+ ASSERT (FALSE);\r
+ return 0;\r
+}\r
+\r
+/**\r
+ See if YEAR field of a variable of EFI_TIME type is correct.\r
+\r
+ @param Time The time to be checked.\r
+\r
+ @retval EFI_INVALID_PARAMETER Some fields of Time are not correct.\r
+ @retval EFI_SUCCESS Time is a valid EFI_TIME variable.\r
+\r
+**/\r
+EFI_STATUS\r
+CheckRtcTimeFields (\r
+ IN EFI_TIME *Time\r
+ )\r
+{\r
+ UINT16 YearBuilt;\r
+ \r
+ YearBuilt = (UINT16)(CharToUint(mBiosReleaseDate[8])*10 + CharToUint(mBiosReleaseDate[9]) + 2000);\r
+ \r
+ if ((Time->Year) < YearBuilt) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ ExitPmAuth Protocol notification event handler, which set initial system time to be\r
+ the time when BIOS was built.\r
+\r
+ @param[in] Event Event whose notification function is being invoked.\r
+ @param[in] Context Pointer to the notification function's context.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+AdjustDefaultRtcTimeCallback (\r
+ IN EFI_EVENT Event,\r
+ IN VOID *Context\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_TIME EfiTime;\r
+ CHAR16 BiosVersion[60]; \r
+ CHAR16 BiosReleaseTime[20]; \r
+ //\r
+ // Get BIOS built time from Bios-ID. \r
+ //\r
+ \r
+ SetMem(BiosVersion, sizeof(BiosVersion), 0);\r
+ SetMem(mBiosReleaseDate, sizeof(mBiosReleaseDate), 0);\r
+ SetMem(BiosReleaseTime, sizeof(BiosReleaseTime), 0);\r
+ \r
+ Status = GetBiosVersionDateTime (BiosVersion, mBiosReleaseDate, BiosReleaseTime);\r
+ ASSERT_EFI_ERROR(Status);\r
+ if (EFI_ERROR (Status)) {\r
+ return; \r
+ }\r
+ \r
+ //\r
+ // Get current RTC time.\r
+ // \r
+ Status = gRT->GetTime (&EfiTime, NULL);\r
+ \r
+ //\r
+ // Validate RTC time fields\r
+ //\r
+ Status = CheckRtcTimeFields (&EfiTime);\r
+ \r
+ if (EFI_ERROR (Status)) {\r
+ //\r
+ // Date such as Dec 28th of 2015\r
+ //\r
+ // Month\r
+ // BiosReleaseDate[0] = '1';\r
+ // BiosReleaseDate[1] = '2';\r
+ //\r
+ // Day\r
+ // BiosReleaseDate[3] = '2';\r
+ // BiosReleaseDate[4] = '8';\r
+ // \r
+ //\r
+ // Year\r
+ //\r
+ // BiosReleaseDate[6] = '2';\r
+ // BiosReleaseDate[7] = '0';\r
+ // BiosReleaseDate[8] = '1'\r
+ // BiosReleaseDate[9] = '5';\r
+ \r
+ EfiTime.Second = RTC_INIT_SECOND;\r
+ EfiTime.Minute = RTC_INIT_MINUTE;\r
+ EfiTime.Hour = RTC_INIT_HOUR;\r
+ EfiTime.Day = (UINT8)(CharToUint(mBiosReleaseDate[3])*10 + CharToUint(mBiosReleaseDate[4]));\r
+ EfiTime.Month = (UINT8)(CharToUint(mBiosReleaseDate[0])*10 + CharToUint(mBiosReleaseDate[1]));\r
+ EfiTime.Year = (UINT16)(CharToUint(mBiosReleaseDate[8])*10 + CharToUint(mBiosReleaseDate[9]) + 2000);\r
+ EfiTime.Nanosecond = 0;\r
+ EfiTime.TimeZone = EFI_UNSPECIFIED_TIMEZONE;\r
+ EfiTime.Daylight = 1; \r
+\r
+ DEBUG ((EFI_D_INFO, "Day:%d Month:%d Year:%d \n", (UINT32)EfiTime.Day, (UINT32)EfiTime.Month, (UINT32)EfiTime.Year));\r
+\r
+ //\r
+ // Reset time value according to new RTC configuration\r
+ //\r
+ Status = gRT->SetTime (&EfiTime);\r
+ ASSERT_EFI_ERROR(Status);\r
+ }\r
+\r
+ return;\r
+}\r