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