1 /** @file
2   Adjust Default System Time.
3 
4   Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>
5 
6   SPDX-License-Identifier: BSD-2-Clause-Patent
7 
8 --*/
9 
10 #include <PlatformDxe.h>
11 
12 //
13 // Date and time initial values.
14 // They are used if the RTC values are invalid during driver initialization
15 //
16 #define RTC_INIT_SECOND 0
17 #define RTC_INIT_MINUTE 0
18 #define RTC_INIT_HOUR   0
19 
20 CHAR16  mBiosReleaseDate[20];
21 
22 /**
23   Convert a single character to number.
24   It assumes the input Char is in the scope of L'0' ~ L'9' and L'A' ~ L'F'
25 
26   @param Char    The input char which need to change to a hex number.
27 
28 **/
29 UINTN
CharToUint(IN CHAR16 Char)30 CharToUint (
31   IN CHAR16                           Char
32   )
33 {
34   if ((Char >= L'0') && (Char <= L'9')) {
35     return (UINTN) (Char - L'0');
36   }
37 
38   if ((Char >= L'A') && (Char <= L'F')) {
39     return (UINTN) (Char - L'A' + 0xA);
40   }
41 
42   ASSERT (FALSE);
43   return 0;
44 }
45 
46 /**
47   See if YEAR field of a variable of EFI_TIME type is correct.
48 
49   @param   Time   The time to be checked.
50 
51   @retval  EFI_INVALID_PARAMETER  Some fields of Time are not correct.
52   @retval  EFI_SUCCESS            Time is a valid EFI_TIME variable.
53 
54 **/
55 EFI_STATUS
CheckRtcTimeFields(IN EFI_TIME * Time)56 CheckRtcTimeFields (
57   IN EFI_TIME *Time
58   )
59 {
60   UINT16 YearBuilt;
61 
62   YearBuilt = (UINT16)(CharToUint(mBiosReleaseDate[8])*10 + CharToUint(mBiosReleaseDate[9]) + 2000);
63 
64   if ((Time->Year) < YearBuilt) {
65     return EFI_INVALID_PARAMETER;
66   }
67 
68   return EFI_SUCCESS;
69 }
70 
71 /**
72   ExitPmAuth Protocol notification event handler, which set initial system time to be
73   the time when BIOS was built.
74 
75   @param[in] Event    Event whose notification function is being invoked.
76   @param[in] Context  Pointer to the notification function's context.
77 
78 **/
79 VOID
80 EFIAPI
AdjustDefaultRtcTimeCallback(IN EFI_EVENT Event,IN VOID * Context)81 AdjustDefaultRtcTimeCallback (
82   IN EFI_EVENT        Event,
83   IN VOID             *Context
84   )
85 {
86   EFI_STATUS      Status;
87   EFI_TIME        EfiTime;
88   CHAR16          BiosVersion[60];
89   CHAR16          BiosReleaseTime[20];
90   //
91   // Get BIOS built time from Bios-ID.
92   //
93 
94   SetMem(BiosVersion, sizeof(BiosVersion), 0);
95   SetMem(mBiosReleaseDate, sizeof(mBiosReleaseDate), 0);
96   SetMem(BiosReleaseTime, sizeof(BiosReleaseTime), 0);
97 
98   Status = GetBiosVersionDateTime (BiosVersion, mBiosReleaseDate, BiosReleaseTime);
99   ASSERT_EFI_ERROR(Status);
100   if (EFI_ERROR (Status)) {
101     return;
102   }
103 
104   //
105   // Get current RTC time.
106   //
107   Status = gRT->GetTime (&EfiTime, NULL);
108 
109   //
110   // Validate RTC time fields
111   //
112   Status = CheckRtcTimeFields (&EfiTime);
113 
114   if (EFI_ERROR (Status)) {
115     //
116     // Date such as Dec 28th of 2015
117     //
118     // Month
119     // BiosReleaseDate[0] = '1';
120     // BiosReleaseDate[1] = '2';
121     //
122     // Day
123     // BiosReleaseDate[3] = '2';
124     // BiosReleaseDate[4] = '8';
125     //
126     //
127     // Year
128     //
129     // BiosReleaseDate[6] = '2';
130     // BiosReleaseDate[7] = '0';
131     // BiosReleaseDate[8] = '1'
132     // BiosReleaseDate[9] = '5';
133 
134     EfiTime.Second = RTC_INIT_SECOND;
135     EfiTime.Minute = RTC_INIT_MINUTE;
136     EfiTime.Hour   = RTC_INIT_HOUR;
137     EfiTime.Day    = (UINT8)(CharToUint(mBiosReleaseDate[3])*10 + CharToUint(mBiosReleaseDate[4]));
138     EfiTime.Month  = (UINT8)(CharToUint(mBiosReleaseDate[0])*10 + CharToUint(mBiosReleaseDate[1]));
139     EfiTime.Year   = (UINT16)(CharToUint(mBiosReleaseDate[8])*10 + CharToUint(mBiosReleaseDate[9]) + 2000);
140     EfiTime.Nanosecond  = 0;
141     EfiTime.TimeZone = EFI_UNSPECIFIED_TIMEZONE;
142     EfiTime.Daylight = 1;
143 
144     DEBUG ((EFI_D_INFO, "Day:%d Month:%d Year:%d \n", (UINT32)EfiTime.Day, (UINT32)EfiTime.Month, (UINT32)EfiTime.Year));
145 
146     //
147     // Reset time value according to new RTC configuration
148     //
149     Status = gRT->SetTime (&EfiTime);
150     ASSERT_EFI_ERROR(Status);
151   }
152 
153   return;
154 }
155