PcAtChipsetPkg/PcRtc: Fix a Y2K bug
[mirror_edk2.git] / PcAtChipsetPkg / PcatRealTimeClockRuntimeDxe / PcRtc.c
index 23f8d3b..9ec309c 100644 (file)
@@ -100,7 +100,6 @@ PcRtcInit (
   RTC_REGISTER_A  RegisterA;\r
   RTC_REGISTER_B  RegisterB;\r
   RTC_REGISTER_D  RegisterD;\r
-  UINT8           Century;\r
   EFI_TIME        Time;\r
   UINTN           DataSize;\r
   UINT32          TimerVar;\r
@@ -163,8 +162,6 @@ PcRtcInit (
   Time.Month  = RtcRead (RTC_ADDRESS_MONTH);\r
   Time.Year   = RtcRead (RTC_ADDRESS_YEAR);\r
 \r
-  Century = RtcRead (RTC_ADDRESS_CENTURY);\r
-  \r
   //\r
   // Set RTC configuration after get original time\r
   // The value of bit AIE should be reserved.\r
@@ -201,7 +198,7 @@ PcRtcInit (
   //\r
   // Validate time fields\r
   //\r
-  Status = ConvertRtcTimeToEfiTime (&Time, Century, RegisterB);\r
+  Status = ConvertRtcTimeToEfiTime (&Time, RegisterB);\r
   if (!EFI_ERROR (Status)) {\r
     Status = RtcTimeFieldsValid (&Time);\r
   }\r
@@ -218,7 +215,7 @@ PcRtcInit (
     Time.Hour   = RTC_INIT_HOUR;\r
     Time.Day    = RTC_INIT_DAY;\r
     Time.Month  = RTC_INIT_MONTH;\r
-    Time.Year   = RTC_INIT_YEAR;\r
+    Time.Year   = PcdGet16 (PcdMinimalValidYear);\r
     Time.Nanosecond  = 0;\r
     Time.TimeZone = EFI_UNSPECIFIED_TIMEZONE;\r
     Time.Daylight = 0;\r
@@ -251,7 +248,7 @@ PcRtcInit (
   Time.Hour   = RTC_INIT_HOUR;\r
   Time.Day    = RTC_INIT_DAY;\r
   Time.Month  = RTC_INIT_MONTH;\r
-  Time.Year   = RTC_INIT_YEAR;\r
+  Time.Year   = PcdGet16 (PcdMinimalValidYear);\r
   Time.Nanosecond  = 0;\r
   Time.TimeZone = Global->SavedTimeZone;\r
   Time.Daylight = Global->Daylight;;\r
@@ -272,8 +269,8 @@ PcRtcInit (
     }\r
     return EFI_DEVICE_ERROR;\r
   }\r
-  \r
-  ConvertEfiTimeToRtcTime (&Time, RegisterB, &Century);\r
+\r
+  ConvertEfiTimeToRtcTime (&Time, RegisterB);\r
 \r
   //\r
   // Set the Y/M/D info to variable as it has no corresponding hw registers.\r
@@ -343,7 +340,6 @@ PcRtcGetTime (
 {\r
   EFI_STATUS      Status;\r
   RTC_REGISTER_B  RegisterB;\r
-  UINT8           Century;\r
 \r
   //\r
   // Check parameters for null pointer\r
@@ -383,8 +379,6 @@ PcRtcGetTime (
   Time->Month   = RtcRead (RTC_ADDRESS_MONTH);\r
   Time->Year    = RtcRead (RTC_ADDRESS_YEAR);\r
 \r
-  Century = RtcRead (RTC_ADDRESS_CENTURY);\r
-  \r
   //\r
   // Release RTC Lock.\r
   //\r
@@ -401,7 +395,7 @@ PcRtcGetTime (
   //\r
   // Make sure all field values are in correct range\r
   //\r
-  Status = ConvertRtcTimeToEfiTime (Time, Century, RegisterB);\r
+  Status = ConvertRtcTimeToEfiTime (Time, RegisterB);\r
   if (!EFI_ERROR (Status)) {\r
     Status = RtcTimeFieldsValid (Time);\r
   }\r
@@ -447,7 +441,6 @@ PcRtcSetTime (
   EFI_STATUS      Status;\r
   EFI_TIME        RtcTime;\r
   RTC_REGISTER_B  RegisterB;\r
-  UINT8           Century;\r
   UINT32          TimerVar;\r
 \r
   if (Time == NULL) {\r
@@ -506,7 +499,7 @@ PcRtcSetTime (
   RegisterB.Bits.Set  = 1;\r
   RtcWrite (RTC_ADDRESS_REGISTER_B, RegisterB.Data);\r
 \r
-  ConvertEfiTimeToRtcTime (&RtcTime, RegisterB, &Century);\r
+  ConvertEfiTimeToRtcTime (&RtcTime, RegisterB);\r
 \r
   RtcWrite (RTC_ADDRESS_SECONDS, RtcTime.Second);\r
   RtcWrite (RTC_ADDRESS_MINUTES, RtcTime.Minute);\r
@@ -514,7 +507,6 @@ PcRtcSetTime (
   RtcWrite (RTC_ADDRESS_DAY_OF_THE_MONTH, RtcTime.Day);\r
   RtcWrite (RTC_ADDRESS_MONTH, RtcTime.Month);\r
   RtcWrite (RTC_ADDRESS_YEAR, (UINT8) RtcTime.Year);\r
-  RtcWrite (RTC_ADDRESS_CENTURY, Century);\r
 \r
   //\r
   // Allow updates of the RTC registers\r
@@ -564,7 +556,6 @@ PcRtcGetWakeupTime (
   EFI_STATUS      Status;\r
   RTC_REGISTER_B  RegisterB;\r
   RTC_REGISTER_C  RegisterC;\r
-  UINT8           Century;\r
   EFI_TIME        RtcTime;\r
   UINTN           DataSize;\r
 \r
@@ -612,8 +603,6 @@ PcRtcGetWakeupTime (
   Time->TimeZone = Global->SavedTimeZone;\r
   Time->Daylight = Global->Daylight;\r
 \r
-  Century = RtcRead (RTC_ADDRESS_CENTURY);\r
-\r
   //\r
   // Get the alarm info from variable\r
   //\r
@@ -644,7 +633,7 @@ PcRtcGetWakeupTime (
   //\r
   // Make sure all field values are in correct range\r
   //\r
-  Status = ConvertRtcTimeToEfiTime (Time, Century, RegisterB);\r
+  Status = ConvertRtcTimeToEfiTime (Time, RegisterB);\r
   if (!EFI_ERROR (Status)) {\r
     Status = RtcTimeFieldsValid (Time);\r
   }\r
@@ -680,7 +669,6 @@ PcRtcSetWakeupTime (
   EFI_STATUS            Status;\r
   EFI_TIME              RtcTime;\r
   RTC_REGISTER_B        RegisterB;\r
-  UINT8                 Century;\r
   EFI_TIME_CAPABILITIES Capabilities;\r
 \r
   ZeroMem (&RtcTime, sizeof (RtcTime));\r
@@ -736,7 +724,7 @@ PcRtcSetWakeupTime (
   RegisterB.Data = RtcRead (RTC_ADDRESS_REGISTER_B);\r
 \r
   if (Enable) {\r
-    ConvertEfiTimeToRtcTime (&RtcTime, RegisterB, &Century);\r
+    ConvertEfiTimeToRtcTime (&RtcTime, RegisterB);\r
   } else {\r
     //\r
     // if the alarm is disable, record the current setting.\r
@@ -837,7 +825,6 @@ CheckAndConvertBcd8ToDecimal8 (
 \r
   @param   Time       On input, the time data read from RTC to convert\r
                       On output, the time converted to UEFI format\r
-  @param   Century    Value of century read from RTC.\r
   @param   RegisterB  Value of Register B of RTC, indicating data mode\r
                       and hour format.\r
 \r
@@ -848,11 +835,11 @@ CheckAndConvertBcd8ToDecimal8 (
 EFI_STATUS\r
 ConvertRtcTimeToEfiTime (\r
   IN OUT EFI_TIME        *Time,\r
-  IN     UINT8           Century,\r
   IN     RTC_REGISTER_B  RegisterB\r
   )\r
 {\r
   BOOLEAN IsPM;\r
+  UINT8   Century;\r
 \r
   if ((Time->Hour & 0x80) != 0) {\r
     IsPM = TRUE;\r
@@ -870,14 +857,21 @@ ConvertRtcTimeToEfiTime (
     Time->Minute  = CheckAndConvertBcd8ToDecimal8 (Time->Minute);\r
     Time->Second  = CheckAndConvertBcd8ToDecimal8 (Time->Second);\r
   }\r
-  Century       = CheckAndConvertBcd8ToDecimal8 (Century);\r
 \r
   if (Time->Year == 0xff || Time->Month == 0xff || Time->Day == 0xff ||\r
-      Time->Hour == 0xff || Time->Minute == 0xff || Time->Second == 0xff ||\r
-      Century == 0xff) {\r
+      Time->Hour == 0xff || Time->Minute == 0xff || Time->Second == 0xff) {\r
     return EFI_INVALID_PARAMETER;\r
   }\r
 \r
+  //\r
+  // For minimal/maximum year range [1970, 2069],\r
+  //   Century is 19 if RTC year >= 70,\r
+  //   Century is 20 otherwise.\r
+  //\r
+  Century = (UINT8) (PcdGet16 (PcdMinimalValidYear) / 100);\r
+  if (Time->Year < PcdGet16 (PcdMinimalValidYear) % 100) {\r
+    Century++;\r
+  }\r
   Time->Year = (UINT16) (Century * 100 + Time->Year);\r
 \r
   //\r
@@ -1053,14 +1047,11 @@ IsLeapYear (
   @param   Time       On input, the time data read from UEFI to convert\r
                       On output, the time converted to RTC format\r
   @param   RegisterB  Value of Register B of RTC, indicating data mode\r
-  @param   Century    It is set according to EFI_TIME Time.\r
-\r
 **/\r
 VOID\r
 ConvertEfiTimeToRtcTime (\r
   IN OUT EFI_TIME        *Time,\r
-  IN     RTC_REGISTER_B  RegisterB,\r
-     OUT UINT8           *Century\r
+  IN     RTC_REGISTER_B  RegisterB\r
   )\r
 {\r
   BOOLEAN IsPM;\r
@@ -1081,10 +1072,8 @@ ConvertEfiTimeToRtcTime (
     }\r
   }\r
   //\r
-  // Set the Time/Date/Daylight Savings values.\r
+  // Set the Time/Date values.\r
   //\r
-  *Century    = DecimalToBcd8 ((UINT8) (Time->Year / 100));\r
-\r
   Time->Year  = (UINT16) (Time->Year % 100);\r
 \r
   if (RegisterB.Bits.Dm == 0) {\r