pointer verification (not NULL) and buffer overrun fixes.
[mirror_edk2.git] / ShellPkg / Library / UefiShellLevel2CommandsLib / TimeDate.c
1 /** @file\r
2   Main file for time, timezone, and date shell level 2 and shell level 3 functions.\r
3 \r
4   Copyright (c) 2009 - 2011, Intel Corporation. All rights reserved.<BR>\r
5   This program and the accompanying materials\r
6   are licensed and made available under the terms and conditions of the BSD License\r
7   which accompanies this distribution.  The full text of the license may be found at\r
8   http://opensource.org/licenses/bsd-license.php\r
9 \r
10   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
11   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
12 \r
13 **/\r
14 \r
15 #include "UefiShellLevel2CommandsLib.h"\r
16 \r
17 /**\r
18   Determine if String is a valid representation for a time or date.\r
19 \r
20   @param[in] String     The pointer to the string to test.\r
21   @param[in] Char       The delimeter character.\r
22   @param[in] Min        The minimum value allowed.\r
23   @param[in] Max        The maximum value allowed.\r
24   @param[in] MinusOk    Whether negative numbers are permitted.\r
25 \r
26   @retval TRUE    String is a valid representation.\r
27   @retval FALSE   String is invalid.\r
28 **/\r
29 BOOLEAN\r
30 EFIAPI\r
31 InternalIsTimeLikeString (\r
32   IN CONST CHAR16   *String,\r
33   IN CONST CHAR16   Char,\r
34   IN CONST UINTN    Min,\r
35   IN CONST UINTN    Max,\r
36   IN CONST BOOLEAN  MinusOk\r
37   )\r
38 {\r
39   UINTN Count;\r
40   Count = 0;\r
41 \r
42   if (MinusOk) {\r
43     //\r
44     // A single minus is ok.\r
45     //\r
46     if (*String == L'-') {\r
47       String++;\r
48     }\r
49   }\r
50 \r
51   //\r
52   // the first char must be numeric.\r
53   //\r
54   if (!ShellIsDecimalDigitCharacter(*String)) {\r
55     return (FALSE);\r
56   }\r
57   //\r
58   // loop through the characters and use the lib function\r
59   //\r
60   for ( ; String != NULL && *String != CHAR_NULL ; String++){\r
61     if (*String == Char) {\r
62       Count++;\r
63       if (Count > Max) {\r
64         return (FALSE);\r
65       }\r
66       continue;\r
67     }\r
68     if (!ShellIsDecimalDigitCharacter(*String)) {\r
69       return (FALSE);\r
70     }\r
71   }\r
72   if (Count < Min) {\r
73     return (FALSE);\r
74   }\r
75   return (TRUE);\r
76 }\r
77 \r
78 /**\r
79   Verify that the DateString is valid and if so set that as the current \r
80   date.\r
81 \r
82   @param[in] DateString     The pointer to a string representation of the date.\r
83 \r
84   @retval SHELL_INVALID_PARAMETER   DateString was NULL.\r
85   @retval SHELL_INVALID_PARAMETER   DateString was mis-formatted.\r
86   @retval SHELL_SUCCESS             The operation was successful.\r
87 **/\r
88 SHELL_STATUS\r
89 EFIAPI\r
90 CheckAndSetDate (\r
91   IN CONST CHAR16 *DateString\r
92   )\r
93 {\r
94   EFI_TIME      TheTime;\r
95   EFI_STATUS    Status;\r
96   CHAR16        *DateStringCopy;\r
97   CHAR16        *Walker;\r
98   CHAR16        *Walker1;\r
99 \r
100   if (!InternalIsTimeLikeString(DateString, L'/', 2, 2, FALSE)) {\r
101     return (SHELL_INVALID_PARAMETER);\r
102   }\r
103 \r
104   Status = gRT->GetTime(&TheTime, NULL);\r
105   ASSERT_EFI_ERROR(Status);\r
106 \r
107   DateStringCopy = NULL;\r
108   DateStringCopy = StrnCatGrow(&DateStringCopy, NULL, DateString, 0);\r
109   if (DateStringCopy == NULL) {\r
110     return (SHELL_OUT_OF_RESOURCES);\r
111   }\r
112   Walker = DateStringCopy;\r
113 \r
114   TheTime.Month = 0xFF;\r
115   TheTime.Day   = 0xFF;\r
116   TheTime.Year  = 0xFFFF;\r
117 \r
118   Walker1 = StrStr(Walker, L"/");\r
119   if (Walker1 != NULL && *Walker1 == L'/') {\r
120     *Walker1 = CHAR_NULL;\r
121   }\r
122 \r
123   TheTime.Month = (UINT8)ShellStrToUintn (Walker);\r
124   if (Walker1 != NULL) {\r
125     Walker = Walker1 + 1;\r
126   }\r
127   Walker1 = Walker!=NULL?StrStr(Walker, L"/"):NULL;\r
128   if (Walker1 != NULL && *Walker1 == L'/') {\r
129     *Walker1 = CHAR_NULL;\r
130   }\r
131   if (Walker != NULL && Walker[0] != CHAR_NULL) {\r
132     TheTime.Day = (UINT8)ShellStrToUintn (Walker);\r
133     if (Walker1 != NULL) {\r
134       Walker = Walker1 + 1;\r
135     }\r
136     Walker1 = Walker!=NULL?StrStr(Walker, L"/"):NULL;\r
137     if (Walker1 != NULL && *Walker1 == L'/') {\r
138       *Walker1 = CHAR_NULL;\r
139     }\r
140     if (Walker != NULL && Walker[0] != CHAR_NULL) {\r
141       TheTime.Year = (UINT16)ShellStrToUintn (Walker);\r
142     }\r
143   }\r
144 \r
145   if (TheTime.Year < 100) {\r
146     if (TheTime.Year >= 98) {\r
147       TheTime.Year = (UINT16)(1900 + TheTime.Year);\r
148     } else {\r
149       TheTime.Year = (UINT16)(2000 + TheTime.Year);\r
150     }\r
151   }\r
152 \r
153   Status = gRT->SetTime(&TheTime);\r
154 \r
155   if (!EFI_ERROR(Status)){\r
156     return (SHELL_SUCCESS);\r
157   }\r
158   return (SHELL_INVALID_PARAMETER);\r
159 }\r
160 \r
161 /**\r
162   Function for 'date' command.\r
163 \r
164   @param[in] ImageHandle  Handle to the Image (NULL if Internal).\r
165   @param[in] SystemTable  Pointer to the System Table (NULL if Internal).\r
166 **/\r
167 SHELL_STATUS\r
168 EFIAPI\r
169 ShellCommandRunDate (\r
170   IN EFI_HANDLE        ImageHandle,\r
171   IN EFI_SYSTEM_TABLE  *SystemTable\r
172   )\r
173 {\r
174   EFI_STATUS    Status;\r
175   LIST_ENTRY    *Package;\r
176   EFI_TIME      TheTime;\r
177   CHAR16        *ProblemParam;\r
178   SHELL_STATUS  ShellStatus;\r
179 \r
180   ShellStatus  = SHELL_SUCCESS;\r
181   ProblemParam = NULL;\r
182 \r
183   //\r
184   // initialize the shell lib (we must be in non-auto-init...)\r
185   //\r
186   Status = ShellInitialize();\r
187   ASSERT_EFI_ERROR(Status);\r
188 \r
189   //\r
190   // parse the command line\r
191   //\r
192   Status = ShellCommandLineParse (SfoParamList, &Package, &ProblemParam, TRUE);\r
193   if (EFI_ERROR(Status)) {\r
194     if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) {\r
195       ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellLevel2HiiHandle, ProblemParam);\r
196       FreePool(ProblemParam);\r
197       ShellStatus = SHELL_INVALID_PARAMETER;\r
198     } else {\r
199       ASSERT(FALSE);\r
200     }\r
201   } else {\r
202     //\r
203     // check for "-?"\r
204     //\r
205     if (ShellCommandLineGetFlag(Package, L"-?")) {\r
206       ASSERT(FALSE);\r
207     } else if (ShellCommandLineGetRawValue(Package, 2) != NULL) {\r
208       ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellLevel2HiiHandle);\r
209       ShellStatus = SHELL_INVALID_PARAMETER;\r
210     } else {\r
211       //\r
212       // If there are 0 value parameters, then print the current date\r
213       // else If there are any value paramerers, then print error\r
214       //\r
215       if (ShellCommandLineGetRawValue(Package, 1) == NULL) {\r
216         //\r
217         // get the current date\r
218         //\r
219         Status = gRT->GetTime(&TheTime, NULL);\r
220         ASSERT_EFI_ERROR(Status);\r
221 \r
222         //\r
223         // ShellPrintEx the date in SFO or regular format\r
224         //\r
225         if (ShellCommandLineGetFlag(Package, L"-sfo")) {\r
226           ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_DATE_SFO_FORMAT), gShellLevel2HiiHandle, TheTime.Month, TheTime.Day, TheTime.Year);\r
227         } else {\r
228           ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_DATE_FORMAT), gShellLevel2HiiHandle, TheTime.Month, TheTime.Day, TheTime.Year);\r
229         }\r
230       } else {\r
231         if (PcdGet8(PcdShellSupportLevel) == 2) {\r
232           ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellLevel2HiiHandle);\r
233           ShellStatus = SHELL_INVALID_PARAMETER;\r
234         } else {\r
235           //\r
236           // perform level 3 operation here.\r
237           //\r
238           ShellStatus = CheckAndSetDate(ShellCommandLineGetRawValue(Package, 1));\r
239           if (ShellStatus != SHELL_SUCCESS) {\r
240             ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellLevel2HiiHandle, ShellCommandLineGetRawValue(Package, 1));\r
241             ShellStatus = SHELL_INVALID_PARAMETER;\r
242           }\r
243         }\r
244       }\r
245     }\r
246   }\r
247   //\r
248   // free the command line package\r
249   //\r
250   ShellCommandLineFreeVarList (Package);\r
251 \r
252   //\r
253   // return the status\r
254   //\r
255   return (ShellStatus);\r
256 }\r
257 \r
258 //\r
259 // Note "-tz" is invalid for this (non-interactive) version of 'time'.\r
260 //\r
261 STATIC CONST SHELL_PARAM_ITEM TimeParamList2[] = {\r
262   {L"-d", TypeValue},\r
263   {NULL, TypeMax}\r
264   };\r
265 \r
266 STATIC CONST SHELL_PARAM_ITEM TimeParamList3[] = {\r
267   {L"-d", TypeValue},\r
268   {L"-tz", TypeValue},\r
269   {NULL, TypeMax}\r
270   };\r
271 \r
272 /**\r
273   Verify that the TimeString is valid and if so set that as the current \r
274   time.\r
275 \r
276   @param[in] TimeString     The pointer to a string representation of the time.\r
277   @param[in] Tz             The value to set for TimeZone.\r
278   @param[in] Daylight       The value to set for Daylight.\r
279 \r
280   @retval SHELL_INVALID_PARAMETER   TimeString was NULL.\r
281   @retval SHELL_INVALID_PARAMETER   TimeString was mis-formatted.\r
282   @retval SHELL_SUCCESS             The operation was successful.\r
283 **/\r
284 SHELL_STATUS\r
285 EFIAPI\r
286 CheckAndSetTime (\r
287   IN CONST CHAR16 *TimeString,\r
288   IN CONST INT16  Tz,\r
289   IN CONST UINT8  Daylight\r
290   )\r
291 {\r
292   EFI_TIME      TheTime;\r
293   EFI_STATUS    Status;\r
294   CHAR16        *TimeStringCopy;\r
295   CHAR16        *Walker1;\r
296   CHAR16        *Walker2;\r
297 \r
298   if (TimeString != NULL && !InternalIsTimeLikeString(TimeString, L':', 1, 2, FALSE)) {\r
299     return (SHELL_INVALID_PARAMETER);\r
300   }\r
301   if (((Daylight & (EFI_TIME_IN_DAYLIGHT|EFI_TIME_ADJUST_DAYLIGHT)) != Daylight)) {\r
302     return (SHELL_INVALID_PARAMETER);\r
303   }\r
304 \r
305   Status = gRT->GetTime(&TheTime, NULL);\r
306   ASSERT_EFI_ERROR(Status);\r
307 \r
308   if (TimeString != NULL) {\r
309     TimeStringCopy = NULL;\r
310     TimeStringCopy = StrnCatGrow(&TimeStringCopy, NULL, TimeString, 0);\r
311     Walker1          = TimeStringCopy;\r
312     TheTime.Hour    = 0xFF;\r
313     TheTime.Minute  = 0xFF;\r
314 \r
315     Walker2          = Walker1!=NULL?StrStr(Walker1, L":"):NULL;\r
316     if (Walker2 != NULL && *Walker2 == L':') {\r
317       *Walker2 = CHAR_NULL;\r
318     }\r
319     TheTime.Hour    = (UINT8)ShellStrToUintn (Walker1);\r
320     if (Walker2 != NULL) {\r
321       Walker1 = Walker2 + 1;\r
322     }\r
323     Walker2          = Walker1!=NULL?StrStr(Walker1, L":"):NULL;\r
324     if (Walker2 != NULL && *Walker2 == L':') {\r
325       *Walker2 = CHAR_NULL;\r
326     }\r
327     if (Walker1 != NULL && Walker1[0] != CHAR_NULL) {\r
328       TheTime.Minute = (UINT8)ShellStrToUintn (Walker1);\r
329       if (Walker2 != NULL) {\r
330         Walker1 = Walker2 + 1;\r
331       }\r
332       if (Walker1 != NULL && Walker1[0] != CHAR_NULL) {\r
333         TheTime.Second = (UINT8)ShellStrToUintn (Walker1);\r
334       }\r
335     }\r
336     SHELL_FREE_NON_NULL(TimeStringCopy);\r
337   }\r
338 \r
339 \r
340   if ((Tz >= -1440 && Tz <= 1440)||(Tz == 0x7FF)) {\r
341     TheTime.TimeZone = Tz;\r
342   }\r
343 \r
344   TheTime.Daylight = Daylight;\r
345 \r
346   Status = gRT->SetTime(&TheTime);\r
347 \r
348   if (!EFI_ERROR(Status)){\r
349     return (SHELL_SUCCESS);\r
350   }\r
351 \r
352   return (SHELL_INVALID_PARAMETER);\r
353 }\r
354 \r
355 /**\r
356   Function for 'time' command.\r
357 \r
358   @param[in] ImageHandle  Handle to the Image (NULL if Internal).\r
359   @param[in] SystemTable  Pointer to the System Table (NULL if Internal).\r
360 **/\r
361 SHELL_STATUS\r
362 EFIAPI\r
363 ShellCommandRunTime (\r
364   IN EFI_HANDLE        ImageHandle,\r
365   IN EFI_SYSTEM_TABLE  *SystemTable\r
366   )\r
367 {\r
368   EFI_STATUS    Status;\r
369   LIST_ENTRY    *Package;\r
370   CHAR16        *Message;\r
371   EFI_TIME      TheTime;\r
372   CHAR16        *ProblemParam;\r
373   SHELL_STATUS  ShellStatus;\r
374   INT16         Tz;\r
375   UINT8         Daylight;\r
376   CONST CHAR16  *TempLocation;\r
377   UINTN         TzMinutes;\r
378 \r
379   ShellStatus  = SHELL_SUCCESS;\r
380   ProblemParam = NULL;\r
381 \r
382   //\r
383   // Initialize variables\r
384   //\r
385   Message = NULL;\r
386 \r
387   //\r
388   // initialize the shell lib (we must be in non-auto-init...)\r
389   //\r
390   Status = ShellInitialize();\r
391   ASSERT_EFI_ERROR(Status);\r
392 \r
393   //\r
394   // parse the command line\r
395   //\r
396   if (PcdGet8(PcdShellSupportLevel) == 2) {\r
397     Status = ShellCommandLineParseEx (TimeParamList2, &Package, &ProblemParam, TRUE, TRUE);\r
398   } else {\r
399     ASSERT(PcdGet8(PcdShellSupportLevel) == 3);\r
400     Status = ShellCommandLineParseEx (TimeParamList3, &Package, &ProblemParam, TRUE, TRUE);\r
401   }\r
402   if (EFI_ERROR(Status)) {\r
403     if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) {\r
404       ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellLevel2HiiHandle, ProblemParam);\r
405       FreePool(ProblemParam);\r
406       ShellStatus = SHELL_INVALID_PARAMETER;\r
407     } else {\r
408       ASSERT(FALSE);\r
409     }\r
410   } else {\r
411     //\r
412     // check for "-?"\r
413     //\r
414     Status = gRT->GetTime(&TheTime, NULL);\r
415     ASSERT_EFI_ERROR(Status);\r
416     if (ShellCommandLineGetFlag(Package, L"-?")) {\r
417       ASSERT(FALSE);\r
418     } else if (ShellCommandLineGetRawValue(Package, 2) != NULL) {\r
419       ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellLevel2HiiHandle);\r
420       ShellStatus = SHELL_INVALID_PARAMETER;\r
421     } else {\r
422       //\r
423       // If there are no parameters, then print the current time\r
424       //\r
425       if (ShellCommandLineGetRawValue(Package, 1) == NULL\r
426         && !ShellCommandLineGetFlag(Package, L"-d")\r
427         && !ShellCommandLineGetFlag(Package, L"-tz")) {\r
428         //\r
429         // ShellPrintEx the current time\r
430         //\r
431         if (TheTime.TimeZone == 2047) {\r
432           TzMinutes = 0;\r
433         } else {\r
434           TzMinutes = (ABS(TheTime.TimeZone)) % 60;\r
435         }\r
436 \r
437         ShellPrintHiiEx (\r
438           -1,\r
439           -1,\r
440           NULL,\r
441           STRING_TOKEN (STR_TIME_FORMAT),\r
442           gShellLevel2HiiHandle,\r
443           TheTime.Hour,\r
444           TheTime.Minute,\r
445           TheTime.Second,\r
446           TheTime.TimeZone==2047?L" ":(TheTime.TimeZone > 0?L"-":L"+"),\r
447           TheTime.TimeZone==2047?0:(ABS(TheTime.TimeZone)) / 60,\r
448           TzMinutes\r
449          );\r
450          ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_CRLF), gShellLevel2HiiHandle);\r
451       } else if (ShellCommandLineGetFlag(Package, L"-d") && ShellCommandLineGetValue(Package, L"-d") == NULL) {\r
452         if (TheTime.TimeZone == 2047) {\r
453           TzMinutes = 0;\r
454         } else {\r
455           TzMinutes = (ABS(TheTime.TimeZone)) % 60;\r
456         }\r
457 \r
458         ShellPrintHiiEx (\r
459           -1,\r
460           -1,\r
461           NULL,\r
462           STRING_TOKEN (STR_TIME_FORMAT),\r
463           gShellLevel2HiiHandle,\r
464           TheTime.Hour,\r
465           TheTime.Minute,\r
466           TheTime.Second,\r
467           TheTime.TimeZone==2047?L" ":(TheTime.TimeZone > 0?L"-":L"+"),\r
468           TheTime.TimeZone==2047?0:(ABS(TheTime.TimeZone)) / 60,\r
469           TzMinutes\r
470          );\r
471           switch (TheTime.Daylight) {\r
472             case 0:\r
473               ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_TIME_DST0), gShellLevel2HiiHandle);\r
474               break;\r
475             case EFI_TIME_ADJUST_DAYLIGHT:\r
476               ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_TIME_DST1), gShellLevel2HiiHandle);\r
477               break;\r
478             case EFI_TIME_IN_DAYLIGHT:\r
479               ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_TIME_DST2), gShellLevel2HiiHandle);\r
480               break;\r
481             case EFI_TIME_IN_DAYLIGHT|EFI_TIME_ADJUST_DAYLIGHT:\r
482               ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_TIME_DST3), gShellLevel2HiiHandle);\r
483               break;\r
484             default:\r
485               ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_UEFI_FUNC_ERROR), gShellLevel2HiiHandle, L"gRT->GetTime", L"TheTime.Daylight", TheTime.Daylight);\r
486           }\r
487       } else {\r
488         if (PcdGet8(PcdShellSupportLevel) == 2) {\r
489           ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellLevel2HiiHandle);\r
490           ShellStatus = SHELL_INVALID_PARAMETER;\r
491         } else {\r
492           //\r
493           // perform level 3 operation here.\r
494           //\r
495           if ((TempLocation = ShellCommandLineGetValue(Package, L"-tz")) != NULL) {\r
496             if (TempLocation[0] == L'-') {\r
497               Tz = (INT16)(0 - ShellStrToUintn(++TempLocation));\r
498             } else {\r
499               Tz = (INT16)ShellStrToUintn(TempLocation);\r
500             }\r
501             if (!(Tz >= -1440 && Tz <= 1440) && Tz != 2047) {\r
502               ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM_VAL), gShellLevel2HiiHandle, L"-tz");\r
503               ShellStatus = SHELL_INVALID_PARAMETER;\r
504             }\r
505           } else {\r
506             //\r
507             // intentionally out of bounds value will prevent changing it...\r
508             //\r
509             Tz = 1441;\r
510           }\r
511           TempLocation = ShellCommandLineGetValue(Package, L"-d");\r
512           if (TempLocation != NULL) {\r
513             Daylight = (UINT8)ShellStrToUintn(TempLocation);\r
514             if (Daylight != 0 && Daylight != 1 && Daylight != 3) {\r
515               ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM_VAL), gShellLevel2HiiHandle, L"-d");\r
516               ShellStatus = SHELL_INVALID_PARAMETER;\r
517             }\r
518           } else {\r
519             //\r
520             // invalid = will not use\r
521             //\r
522             Daylight = 0xFF;\r
523           }\r
524           if (ShellStatus == SHELL_SUCCESS) {\r
525             ShellStatus = CheckAndSetTime(ShellCommandLineGetRawValue(Package, 1), Tz, Daylight);\r
526             if (ShellStatus != SHELL_SUCCESS) {\r
527               ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellLevel2HiiHandle, ShellCommandLineGetRawValue(Package, 1));\r
528               ShellStatus = SHELL_INVALID_PARAMETER;\r
529             }\r
530           }\r
531         }\r
532       }\r
533     }\r
534   }\r
535 \r
536   //\r
537   // free the command line package\r
538   //\r
539   ShellCommandLineFreeVarList (Package);\r
540 \r
541   //\r
542   // return the status\r
543   //\r
544   return (ShellStatus);\r
545 }\r
546 \r
547 typedef struct {\r
548   INT16         TimeZone;\r
549   EFI_STRING_ID StringId;\r
550 } TIME_ZONE_ITEM;\r
551 \r
552 STATIC CONST SHELL_PARAM_ITEM TimeZoneParamList2[] = {\r
553   {L"-l", TypeFlag},\r
554   {L"-f", TypeFlag},\r
555   {NULL, TypeMax}\r
556   };\r
557 STATIC CONST SHELL_PARAM_ITEM TimeZoneParamList3[] = {\r
558   {L"-l", TypeFlag},\r
559   {L"-f", TypeFlag},\r
560   {L"-s", TypeValue},\r
561   {NULL, TypeMax}\r
562   };\r
563 \r
564   STATIC CONST TIME_ZONE_ITEM TimeZoneList[] = {\r
565     {720, STRING_TOKEN (STR_TIMEZONE_M12)},\r
566     {660, STRING_TOKEN (STR_TIMEZONE_M11)},\r
567     {600, STRING_TOKEN (STR_TIMEZONE_M10)},\r
568     {540, STRING_TOKEN (STR_TIMEZONE_M9)},\r
569     {480, STRING_TOKEN (STR_TIMEZONE_M8)},\r
570     {420, STRING_TOKEN (STR_TIMEZONE_M7)},\r
571     {360, STRING_TOKEN (STR_TIMEZONE_M6)},\r
572     {300, STRING_TOKEN (STR_TIMEZONE_M5)},\r
573     {270, STRING_TOKEN (STR_TIMEZONE_M430)},\r
574     {240, STRING_TOKEN (STR_TIMEZONE_M4)},\r
575     {210, STRING_TOKEN (STR_TIMEZONE_M330)},\r
576     {180, STRING_TOKEN (STR_TIMEZONE_M3)},\r
577     {120, STRING_TOKEN (STR_TIMEZONE_M2)},\r
578     {60 , STRING_TOKEN (STR_TIMEZONE_M1)},\r
579     {0   , STRING_TOKEN (STR_TIMEZONE_0)},\r
580     {-60  , STRING_TOKEN (STR_TIMEZONE_P1)},\r
581     {-120 , STRING_TOKEN (STR_TIMEZONE_P2)},\r
582     {-180 , STRING_TOKEN (STR_TIMEZONE_P3)},\r
583     {-210 , STRING_TOKEN (STR_TIMEZONE_P330)},\r
584     {-240 , STRING_TOKEN (STR_TIMEZONE_P4)},\r
585     {-270 , STRING_TOKEN (STR_TIMEZONE_P430)},\r
586     {-300 , STRING_TOKEN (STR_TIMEZONE_P5)},\r
587     {-330 , STRING_TOKEN (STR_TIMEZONE_P530)},\r
588     {-345 , STRING_TOKEN (STR_TIMEZONE_P545)},\r
589     {-360 , STRING_TOKEN (STR_TIMEZONE_P6)},\r
590     {-390 , STRING_TOKEN (STR_TIMEZONE_P630)},\r
591     {-420 , STRING_TOKEN (STR_TIMEZONE_P7)},\r
592     {-480 , STRING_TOKEN (STR_TIMEZONE_P8)},\r
593     {-540 , STRING_TOKEN (STR_TIMEZONE_P9)},\r
594     {-570 , STRING_TOKEN (STR_TIMEZONE_P930)},\r
595     {-600 , STRING_TOKEN (STR_TIMEZONE_P10)},\r
596     {-660 , STRING_TOKEN (STR_TIMEZONE_P11)},\r
597     {-720 , STRING_TOKEN (STR_TIMEZONE_P12)},\r
598     {-780 , STRING_TOKEN (STR_TIMEZONE_P13)},\r
599     {-840 , STRING_TOKEN (STR_TIMEZONE_P14)}\r
600 };\r
601 \r
602 /**\r
603   Verify that the TimeZoneString is valid and if so set that as the current \r
604   timezone.\r
605 \r
606   @param[in] TimeZoneString     The pointer to a string representation of the timezone.\r
607 \r
608   @retval SHELL_INVALID_PARAMETER   TimeZoneString was NULL.\r
609   @retval SHELL_INVALID_PARAMETER   TimeZoneString was mis-formatted.\r
610   @retval SHELL_SUCCESS             The operation was successful.\r
611 **/\r
612 SHELL_STATUS\r
613 EFIAPI\r
614 CheckAndSetTimeZone (\r
615   IN CONST CHAR16 *TimeZoneString\r
616   )\r
617 {\r
618   EFI_TIME      TheTime;\r
619   EFI_STATUS    Status;\r
620   CHAR16        *TimeZoneCopy;\r
621   CHAR16        *Walker;\r
622   CHAR16        *Walker2;\r
623   UINTN         LoopVar;\r
624 \r
625   if (TimeZoneString == NULL) {\r
626     return (SHELL_INVALID_PARAMETER);\r
627   }\r
628 \r
629   if (TimeZoneString != NULL && !InternalIsTimeLikeString(TimeZoneString, L':', 1, 1, TRUE)) {\r
630     return (SHELL_INVALID_PARAMETER);\r
631   }\r
632 \r
633   Status = gRT->GetTime(&TheTime, NULL);\r
634   ASSERT_EFI_ERROR(Status);\r
635 \r
636   TimeZoneCopy = NULL;\r
637   TimeZoneCopy = StrnCatGrow(&TimeZoneCopy, NULL, TimeZoneString, 0);\r
638   Walker = TimeZoneCopy;\r
639   Walker2 = StrStr(Walker, L":");\r
640   if (Walker2 != NULL && *Walker2 == L':') {\r
641     *Walker2 = CHAR_NULL;\r
642   }\r
643   if (*Walker == L'-') {\r
644     TheTime.TimeZone = (INT16)((ShellStrToUintn (++Walker)) * 60);\r
645   } else {\r
646     TheTime.TimeZone = (INT16)((ShellStrToUintn (Walker)) * -60);\r
647   }\r
648   if (Walker2 != NULL) {\r
649     Walker = Walker2 + 1;\r
650   }\r
651   if (Walker != NULL && Walker[0] != CHAR_NULL) {\r
652     if (TheTime.TimeZone < 0) {\r
653       TheTime.TimeZone = (INT16)(TheTime.TimeZone - (UINT8)ShellStrToUintn (Walker));\r
654     } else {\r
655       TheTime.TimeZone = (INT16)(TheTime.TimeZone + (UINT8)ShellStrToUintn (Walker));\r
656     }\r
657   }\r
658 \r
659   Status = EFI_INVALID_PARAMETER;\r
660 \r
661   for ( LoopVar = 0\r
662       ; LoopVar < sizeof(TimeZoneList) / sizeof(TimeZoneList[0])\r
663       ; LoopVar++\r
664      ){\r
665     if (TheTime.TimeZone == TimeZoneList[LoopVar].TimeZone) {\r
666         Status = gRT->SetTime(&TheTime);\r
667         break;\r
668     }\r
669   }\r
670 \r
671   FreePool(TimeZoneCopy);\r
672 \r
673   if (!EFI_ERROR(Status)){\r
674     return (SHELL_SUCCESS);\r
675   }\r
676   return (SHELL_INVALID_PARAMETER);\r
677 }\r
678 \r
679 \r
680 /**\r
681   Function for 'timezone' command.\r
682 \r
683   @param[in] ImageHandle  Handle to the Image (NULL if Internal).\r
684   @param[in] SystemTable  Pointer to the System Table (NULL if Internal).\r
685 **/\r
686 SHELL_STATUS\r
687 EFIAPI\r
688 ShellCommandRunTimeZone (\r
689   IN EFI_HANDLE        ImageHandle,\r
690   IN EFI_SYSTEM_TABLE  *SystemTable\r
691   )\r
692 {\r
693   //\r
694   // non interactive\r
695   //\r
696   EFI_STATUS    Status;\r
697   LIST_ENTRY    *Package;\r
698   CHAR16        *ProblemParam;\r
699   SHELL_STATUS  ShellStatus;\r
700   UINT8         LoopVar;\r
701   EFI_TIME      TheTime;\r
702   BOOLEAN       Found;\r
703   UINTN         TzMinutes;\r
704 \r
705   ShellStatus  = SHELL_SUCCESS;\r
706   ProblemParam = NULL;\r
707 \r
708   //\r
709   // initialize the shell lib (we must be in non-auto-init...)\r
710   //\r
711   Status = ShellInitialize();\r
712   ASSERT_EFI_ERROR(Status);\r
713 \r
714   //\r
715   // parse the command line\r
716   //\r
717   if (PcdGet8(PcdShellSupportLevel) == 2) {\r
718     Status = ShellCommandLineParse (TimeZoneParamList2, &Package, &ProblemParam, FALSE);\r
719   } else {\r
720     ASSERT(PcdGet8(PcdShellSupportLevel) == 3);\r
721     Status = ShellCommandLineParseEx (TimeZoneParamList3, &Package, &ProblemParam, FALSE, TRUE);\r
722   }\r
723   if (EFI_ERROR(Status)) {\r
724     if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) {\r
725       ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellLevel2HiiHandle, ProblemParam);\r
726       FreePool(ProblemParam);\r
727       ShellStatus = SHELL_INVALID_PARAMETER;\r
728     } else {\r
729       ASSERT(FALSE);\r
730     }\r
731   } else {\r
732     //\r
733     // check for "-?"\r
734     //\r
735     if (ShellCommandLineGetCount(Package) > 1) {\r
736       ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellLevel2HiiHandle);\r
737       ShellStatus = SHELL_INVALID_PARAMETER;\r
738     } else if (ShellCommandLineGetFlag(Package, L"-?")) {\r
739       ASSERT(FALSE);\r
740     } else if (ShellCommandLineGetFlag(Package, L"-s")) {\r
741       if ((ShellCommandLineGetFlag(Package, L"-l")) || (ShellCommandLineGetFlag(Package, L"-f"))) {\r
742         ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellLevel2HiiHandle, L"-l or -f");\r
743         ShellStatus = SHELL_INVALID_PARAMETER;\r
744       } else {\r
745         ASSERT(PcdGet8(PcdShellSupportLevel) == 3);\r
746         if (ShellCommandLineGetValue(Package, L"-s") == NULL) {\r
747           ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_VALUE), gShellLevel2HiiHandle, L"-s");\r
748           ShellStatus = SHELL_INVALID_PARAMETER;\r
749         } else {\r
750           //\r
751           // Set the time zone\r
752           //\r
753           ShellStatus = CheckAndSetTimeZone(ShellCommandLineGetValue(Package, L"-s"));\r
754           if (ShellStatus != SHELL_SUCCESS) {\r
755             ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellLevel2HiiHandle, ShellCommandLineGetValue(Package, L"-s"));\r
756             ShellStatus = SHELL_INVALID_PARAMETER;\r
757           }\r
758         }\r
759       }\r
760     } else if (ShellCommandLineGetFlag(Package, L"-l")) {\r
761       //\r
762       // Print a list of all time zones\r
763       //\r
764       for ( LoopVar = 0\r
765           ; LoopVar < sizeof(TimeZoneList) / sizeof(TimeZoneList[0])\r
766           ; LoopVar++\r
767          ){\r
768         ShellPrintHiiEx (-1, -1, NULL, TimeZoneList[LoopVar].StringId, gShellLevel2HiiHandle);\r
769       }\r
770     } else {\r
771       //\r
772       // Get Current Time Zone Info\r
773       //\r
774       Status = gRT->GetTime(&TheTime, NULL);\r
775       ASSERT_EFI_ERROR(Status);\r
776 \r
777       if (TheTime.TimeZone != 2047) {\r
778         Found = FALSE;\r
779         for ( LoopVar = 0\r
780             ; LoopVar < sizeof(TimeZoneList) / sizeof(TimeZoneList[0])\r
781             ; LoopVar++\r
782            ){\r
783           if (TheTime.TimeZone == TimeZoneList[LoopVar].TimeZone) {\r
784             if (ShellCommandLineGetFlag(Package, L"-f")) {\r
785               //\r
786               //  Print all info about current time zone\r
787               //\r
788               ShellPrintHiiEx (-1, -1, NULL, TimeZoneList[LoopVar].StringId, gShellLevel2HiiHandle);\r
789             } else {\r
790               //\r
791               // Print basic info only\r
792               //\r
793               if (TheTime.TimeZone == 2047) {\r
794                 TzMinutes = 0;\r
795               } else {\r
796                 TzMinutes = (ABS(TheTime.TimeZone)) % 60;\r
797               }\r
798 \r
799               ShellPrintHiiEx (\r
800                 -1,\r
801                 -1,\r
802                 NULL,\r
803                 STRING_TOKEN(STR_TIMEZONE_SIMPLE),\r
804                 gShellLevel2HiiHandle,\r
805                 TheTime.TimeZone==2047?0:(TheTime.TimeZone > 0?L"-":L"+"),\r
806                 TheTime.TimeZone==2047?0:(ABS(TheTime.TimeZone)) / 60,\r
807                 TzMinutes);\r
808             }\r
809             Found = TRUE;\r
810             break;\r
811           }\r
812         }\r
813         if (!Found) {\r
814           //\r
815           // Print basic info only\r
816           //\r
817           if (TheTime.TimeZone == 2047) {\r
818             TzMinutes = 0;\r
819           } else {\r
820             TzMinutes = (ABS(TheTime.TimeZone)) % 60;\r
821           }\r
822           ShellPrintHiiEx (\r
823             -1,\r
824             -1,\r
825             NULL,\r
826             STRING_TOKEN(STR_TIMEZONE_SIMPLE),\r
827             gShellLevel2HiiHandle,\r
828             TheTime.TimeZone==2047?0:(TheTime.TimeZone > 0?L"-":L"+"),\r
829             TheTime.TimeZone==2047?0:(ABS(TheTime.TimeZone)) / 60,\r
830             TzMinutes);\r
831           if (ShellCommandLineGetFlag(Package, L"-f")) {\r
832             ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN(STR_TIMEZONE_NI), gShellLevel2HiiHandle);\r
833           }\r
834         }\r
835       } else {\r
836         //\r
837         // TimeZone was 2047 (unknown) from GetTime()\r
838         //\r
839       }\r
840     }\r
841   }\r
842 \r
843   //\r
844   // free the command line package\r
845   //\r
846   ShellCommandLineFreeVarList (Package);\r
847 \r
848   return (ShellStatus);\r
849 }\r