]> git.proxmox.com Git - mirror_edk2.git/blame_incremental - ShellPkg/Library/UefiShellLevel2CommandsLib/TimeDate.c
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[mirror_edk2.git] / ShellPkg / Library / UefiShellLevel2CommandsLib / TimeDate.c
... / ...
CommitLineData
1/** @file\r
2 Main file for time, timezone, and date shell level 2 and shell level 3 functions.\r
3\r
4 (C) Copyright 2012-2015 Hewlett-Packard Development Company, L.P.<BR>\r
5 Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR>\r
6 SPDX-License-Identifier: BSD-2-Clause-Patent\r
7\r
8**/\r
9\r
10#include "UefiShellLevel2CommandsLib.h"\r
11\r
12/**\r
13 Determine if String is a valid representation for a time or date.\r
14\r
15 @param[in] String The pointer to the string to test.\r
16 @param[in] Char The delimeter character.\r
17 @param[in] Min The minimum value allowed.\r
18 @param[in] Max The maximum value allowed.\r
19 @param[in] MinusOk Whether negative numbers are permitted.\r
20\r
21 @retval TRUE String is a valid representation.\r
22 @retval FALSE String is invalid.\r
23**/\r
24BOOLEAN\r
25InternalIsTimeLikeString (\r
26 IN CONST CHAR16 *String,\r
27 IN CONST CHAR16 Char,\r
28 IN CONST UINTN Min,\r
29 IN CONST UINTN Max,\r
30 IN CONST BOOLEAN MinusOk\r
31 )\r
32{\r
33 UINTN Count;\r
34\r
35 Count = 0;\r
36\r
37 if (MinusOk) {\r
38 //\r
39 // A single minus is ok.\r
40 //\r
41 if (*String == L'-') {\r
42 String++;\r
43 }\r
44 }\r
45\r
46 //\r
47 // the first char must be numeric.\r
48 //\r
49 if (!ShellIsDecimalDigitCharacter (*String)) {\r
50 return (FALSE);\r
51 }\r
52\r
53 //\r
54 // loop through the characters and use the lib function\r
55 //\r
56 for ( ; String != NULL && *String != CHAR_NULL; String++) {\r
57 if (*String == Char) {\r
58 Count++;\r
59 if (Count > Max) {\r
60 return (FALSE);\r
61 }\r
62\r
63 continue;\r
64 }\r
65\r
66 if (!ShellIsDecimalDigitCharacter (*String)) {\r
67 return (FALSE);\r
68 }\r
69 }\r
70\r
71 if (Count < Min) {\r
72 return (FALSE);\r
73 }\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
88SHELL_STATUS\r
89CheckAndSetDate (\r
90 IN CONST CHAR16 *DateString\r
91 )\r
92{\r
93 EFI_TIME TheTime;\r
94 EFI_STATUS Status;\r
95 CHAR16 *DateStringCopy;\r
96 CHAR16 *Walker;\r
97 CHAR16 *Walker1;\r
98\r
99 if (!InternalIsTimeLikeString (DateString, L'/', 2, 2, FALSE)) {\r
100 return (SHELL_INVALID_PARAMETER);\r
101 }\r
102\r
103 Status = gRT->GetTime (&TheTime, NULL);\r
104 if (EFI_ERROR (Status)) {\r
105 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_UEFI_FUNC_WARN), gShellLevel2HiiHandle, L"date", L"gRT->GetTime", Status);\r
106 return (SHELL_DEVICE_ERROR);\r
107 }\r
108\r
109 DateStringCopy = NULL;\r
110 DateStringCopy = StrnCatGrow (&DateStringCopy, NULL, DateString, 0);\r
111 if (DateStringCopy == NULL) {\r
112 return (SHELL_OUT_OF_RESOURCES);\r
113 }\r
114\r
115 Walker = DateStringCopy;\r
116\r
117 TheTime.Month = 0xFF;\r
118 TheTime.Day = 0xFF;\r
119 TheTime.Year = 0xFFFF;\r
120\r
121 Walker1 = StrStr (Walker, L"/");\r
122 if ((Walker1 != NULL) && (*Walker1 == L'/')) {\r
123 *Walker1 = CHAR_NULL;\r
124 }\r
125\r
126 TheTime.Month = (UINT8)ShellStrToUintn (Walker);\r
127 if (Walker1 != NULL) {\r
128 Walker = Walker1 + 1;\r
129 }\r
130\r
131 Walker1 = Walker != NULL ? StrStr (Walker, L"/") : NULL;\r
132 if ((Walker1 != NULL) && (*Walker1 == L'/')) {\r
133 *Walker1 = CHAR_NULL;\r
134 }\r
135\r
136 if ((Walker != NULL) && (Walker[0] != CHAR_NULL)) {\r
137 TheTime.Day = (UINT8)ShellStrToUintn (Walker);\r
138 if (Walker1 != NULL) {\r
139 Walker = Walker1 + 1;\r
140 }\r
141\r
142 Walker1 = Walker != NULL ? StrStr (Walker, L"/") : NULL;\r
143 if ((Walker1 != NULL) && (*Walker1 == L'/')) {\r
144 *Walker1 = CHAR_NULL;\r
145 }\r
146\r
147 if ((Walker != NULL) && (Walker[0] != CHAR_NULL)) {\r
148 TheTime.Year = (UINT16)ShellStrToUintn (Walker);\r
149 }\r
150 }\r
151\r
152 if (TheTime.Year < 100) {\r
153 if (TheTime.Year >= 98) {\r
154 TheTime.Year = (UINT16)(1900 + TheTime.Year);\r
155 } else {\r
156 TheTime.Year = (UINT16)(2000 + TheTime.Year);\r
157 }\r
158 }\r
159\r
160 Status = gRT->SetTime (&TheTime);\r
161\r
162 if (!EFI_ERROR (Status)) {\r
163 return (SHELL_SUCCESS);\r
164 }\r
165\r
166 return (SHELL_INVALID_PARAMETER);\r
167}\r
168\r
169/**\r
170 Function for 'date' command.\r
171\r
172 @param[in] ImageHandle Handle to the Image (NULL if Internal).\r
173 @param[in] SystemTable Pointer to the System Table (NULL if Internal).\r
174**/\r
175SHELL_STATUS\r
176EFIAPI\r
177ShellCommandRunDate (\r
178 IN EFI_HANDLE ImageHandle,\r
179 IN EFI_SYSTEM_TABLE *SystemTable\r
180 )\r
181{\r
182 EFI_STATUS Status;\r
183 LIST_ENTRY *Package;\r
184 EFI_TIME TheTime;\r
185 CHAR16 *ProblemParam;\r
186 SHELL_STATUS ShellStatus;\r
187 CONST CHAR16 *Param1;\r
188\r
189 ShellStatus = SHELL_SUCCESS;\r
190 ProblemParam = NULL;\r
191\r
192 //\r
193 // initialize the shell lib (we must be in non-auto-init...)\r
194 //\r
195 Status = ShellInitialize ();\r
196 ASSERT_EFI_ERROR (Status);\r
197\r
198 //\r
199 // parse the command line\r
200 //\r
201 Status = ShellCommandLineParse (SfoParamList, &Package, &ProblemParam, TRUE);\r
202 if (EFI_ERROR (Status)) {\r
203 if ((Status == EFI_VOLUME_CORRUPTED) && (ProblemParam != NULL)) {\r
204 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellLevel2HiiHandle, L"date", ProblemParam);\r
205 FreePool (ProblemParam);\r
206 ShellStatus = SHELL_INVALID_PARAMETER;\r
207 } else {\r
208 ASSERT (FALSE);\r
209 }\r
210 } else {\r
211 //\r
212 // check for "-?"\r
213 //\r
214 if (ShellCommandLineGetFlag (Package, L"-?")) {\r
215 ASSERT (FALSE);\r
216 } else if (ShellCommandLineGetRawValue (Package, 2) != NULL) {\r
217 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellLevel2HiiHandle, L"date");\r
218 ShellStatus = SHELL_INVALID_PARAMETER;\r
219 } else {\r
220 //\r
221 // If there are 0 value parameters, then print the current date\r
222 // else If there are any value paramerers, then print error\r
223 //\r
224 if (ShellCommandLineGetRawValue (Package, 1) == NULL) {\r
225 //\r
226 // get the current date\r
227 //\r
228 Status = gRT->GetTime (&TheTime, NULL);\r
229 if (EFI_ERROR (Status)) {\r
230 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_UEFI_FUNC_WARN), gShellLevel2HiiHandle, L"date", L"gRT->GetTime", Status);\r
231 return (SHELL_DEVICE_ERROR);\r
232 }\r
233\r
234 //\r
235 // ShellPrintEx the date in SFO or regular format\r
236 //\r
237 if (ShellCommandLineGetFlag (Package, L"-sfo")) {\r
238 //\r
239 // Match UEFI Shell spec:\r
240 // ShellCommand,"date"\r
241 // Date,"DD","MM","YYYY"\r
242 //\r
243 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_SFO_HEADER), gShellLevel2HiiHandle, L"date");\r
244 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DATE_SFO_FORMAT), gShellLevel2HiiHandle, TheTime.Day, TheTime.Month, TheTime.Year);\r
245 } else {\r
246 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DATE_FORMAT), gShellLevel2HiiHandle, TheTime.Month, TheTime.Day, TheTime.Year);\r
247 }\r
248 } else {\r
249 if (PcdGet8 (PcdShellSupportLevel) == 2) {\r
250 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellLevel2HiiHandle, L"date");\r
251 ShellStatus = SHELL_INVALID_PARAMETER;\r
252 } else {\r
253 //\r
254 // perform level 3 operation here.\r
255 //\r
256 Param1 = ShellCommandLineGetRawValue (Package, 1);\r
257 if (Param1 == NULL) {\r
258 ShellStatus = SHELL_INVALID_PARAMETER;\r
259 } else {\r
260 ShellStatus = CheckAndSetDate (Param1);\r
261 }\r
262\r
263 if (ShellStatus != SHELL_SUCCESS) {\r
264 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellLevel2HiiHandle, L"date", Param1);\r
265 ShellStatus = SHELL_INVALID_PARAMETER;\r
266 }\r
267 }\r
268 }\r
269 }\r
270 }\r
271\r
272 //\r
273 // free the command line package\r
274 //\r
275 ShellCommandLineFreeVarList (Package);\r
276\r
277 //\r
278 // return the status\r
279 //\r
280 return (ShellStatus);\r
281}\r
282\r
283//\r
284// Note "-tz" is invalid for this (non-interactive) version of 'time'.\r
285//\r
286STATIC CONST SHELL_PARAM_ITEM TimeParamList2[] = {\r
287 { L"-d", TypeValue },\r
288 { NULL, TypeMax }\r
289};\r
290\r
291STATIC CONST SHELL_PARAM_ITEM TimeParamList3[] = {\r
292 { L"-d", TypeValue },\r
293 { L"-tz", TypeValue },\r
294 { NULL, TypeMax }\r
295};\r
296\r
297/**\r
298 Verify that the TimeString is valid and if so set that as the current\r
299 time.\r
300\r
301 @param[in] TimeString The pointer to a string representation of the time.\r
302 @param[in] Tz The value to set for TimeZone.\r
303 @param[in] Daylight The value to set for Daylight.\r
304\r
305 @retval SHELL_INVALID_PARAMETER TimeString was NULL.\r
306 @retval SHELL_INVALID_PARAMETER TimeString was mis-formatted.\r
307 @retval SHELL_SUCCESS The operation was successful.\r
308**/\r
309SHELL_STATUS\r
310CheckAndSetTime (\r
311 IN CONST CHAR16 *TimeString,\r
312 IN CONST INT16 Tz,\r
313 IN CONST UINT8 Daylight\r
314 )\r
315{\r
316 EFI_TIME TheTime;\r
317 EFI_STATUS Status;\r
318 CHAR16 *TimeStringCopy;\r
319 CHAR16 *Walker1;\r
320 CHAR16 *Walker2;\r
321\r
322 if ((TimeString != NULL) && !InternalIsTimeLikeString (TimeString, L':', 1, 2, FALSE)) {\r
323 return (SHELL_INVALID_PARAMETER);\r
324 }\r
325\r
326 if ((Daylight != 0xFF) && ((Daylight & (EFI_TIME_IN_DAYLIGHT|EFI_TIME_ADJUST_DAYLIGHT)) != Daylight)) {\r
327 return (SHELL_INVALID_PARAMETER);\r
328 }\r
329\r
330 Status = gRT->GetTime (&TheTime, NULL);\r
331 if (EFI_ERROR (Status)) {\r
332 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_UEFI_FUNC_WARN), gShellLevel2HiiHandle, L"time", L"gRT->GetTime", Status);\r
333 return (SHELL_DEVICE_ERROR);\r
334 }\r
335\r
336 if (TimeString != NULL) {\r
337 TimeStringCopy = NULL;\r
338 TimeStringCopy = StrnCatGrow (&TimeStringCopy, NULL, TimeString, 0);\r
339 Walker1 = TimeStringCopy;\r
340 TheTime.Hour = 0xFF;\r
341 TheTime.Minute = 0xFF;\r
342\r
343 Walker2 = Walker1 != NULL ? StrStr (Walker1, L":") : NULL;\r
344 if ((Walker2 != NULL) && (*Walker2 == L':')) {\r
345 *Walker2 = CHAR_NULL;\r
346 }\r
347\r
348 TheTime.Hour = (UINT8)ShellStrToUintn (Walker1);\r
349 if (Walker2 != NULL) {\r
350 Walker1 = Walker2 + 1;\r
351 }\r
352\r
353 Walker2 = Walker1 != NULL ? StrStr (Walker1, L":") : NULL;\r
354 if ((Walker2 != NULL) && (*Walker2 == L':')) {\r
355 *Walker2 = CHAR_NULL;\r
356 TheTime.Second = (UINT8)0;\r
357 } else if (Walker2 == NULL) {\r
358 TheTime.Second = (UINT8)0;\r
359 }\r
360\r
361 if ((Walker1 != NULL) && (Walker1[0] != CHAR_NULL)) {\r
362 TheTime.Minute = (UINT8)ShellStrToUintn (Walker1);\r
363 if (Walker2 != NULL) {\r
364 Walker1 = Walker2 + 1;\r
365 if ((Walker1 != NULL) && (Walker1[0] != CHAR_NULL)) {\r
366 TheTime.Second = (UINT8)ShellStrToUintn (Walker1);\r
367 }\r
368 }\r
369 }\r
370\r
371 SHELL_FREE_NON_NULL (TimeStringCopy);\r
372 }\r
373\r
374 if ((Tz >= -1440) && (Tz <= 1440)) {\r
375 //\r
376 // EFI_TIME TimeZone is stored to meet the following calculation (see UEFI Spec):\r
377 // Localtime = UTC - TimeZone\r
378 // This means the sign must be changed for the user provided Tz.\r
379 // EX: User wants to set TimeZone to Pacific Standard Time, so runs\r
380 // time -tz -480 # set to UTC-08:00\r
381 // To meet the calculation, the sign must be changed.\r
382 //\r
383 TheTime.TimeZone = -Tz;\r
384 } else if (Tz == EFI_UNSPECIFIED_TIMEZONE) {\r
385 TheTime.TimeZone = Tz;\r
386 }\r
387\r
388 if (Daylight != 0xFF) {\r
389 TheTime.Daylight = Daylight;\r
390 }\r
391\r
392 Status = gRT->SetTime (&TheTime);\r
393\r
394 if (!EFI_ERROR (Status)) {\r
395 return (SHELL_SUCCESS);\r
396 }\r
397\r
398 return (SHELL_INVALID_PARAMETER);\r
399}\r
400\r
401/**\r
402 Function for 'time' command.\r
403\r
404 @param[in] ImageHandle Handle to the Image (NULL if Internal).\r
405 @param[in] SystemTable Pointer to the System Table (NULL if Internal).\r
406**/\r
407SHELL_STATUS\r
408EFIAPI\r
409ShellCommandRunTime (\r
410 IN EFI_HANDLE ImageHandle,\r
411 IN EFI_SYSTEM_TABLE *SystemTable\r
412 )\r
413{\r
414 EFI_STATUS Status;\r
415 LIST_ENTRY *Package;\r
416 EFI_TIME TheTime;\r
417 CHAR16 *ProblemParam;\r
418 SHELL_STATUS ShellStatus;\r
419 INT16 Tz;\r
420 UINT8 Daylight;\r
421 CONST CHAR16 *TempLocation;\r
422 UINTN TzMinutes;\r
423\r
424 //\r
425 // Initialize variables\r
426 //\r
427 ShellStatus = SHELL_SUCCESS;\r
428 ProblemParam = NULL;\r
429\r
430 //\r
431 // initialize the shell lib (we must be in non-auto-init...)\r
432 //\r
433 Status = ShellInitialize ();\r
434 ASSERT_EFI_ERROR (Status);\r
435\r
436 //\r
437 // parse the command line\r
438 //\r
439 if (PcdGet8 (PcdShellSupportLevel) == 2) {\r
440 Status = ShellCommandLineParseEx (TimeParamList2, &Package, &ProblemParam, TRUE, TRUE);\r
441 } else {\r
442 ASSERT (PcdGet8 (PcdShellSupportLevel) == 3);\r
443 Status = ShellCommandLineParseEx (TimeParamList3, &Package, &ProblemParam, TRUE, TRUE);\r
444 }\r
445\r
446 if (EFI_ERROR (Status)) {\r
447 if ((Status == EFI_VOLUME_CORRUPTED) && (ProblemParam != NULL)) {\r
448 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellLevel2HiiHandle, L"time", ProblemParam);\r
449 FreePool (ProblemParam);\r
450 ShellStatus = SHELL_INVALID_PARAMETER;\r
451 } else {\r
452 ASSERT (FALSE);\r
453 }\r
454 } else {\r
455 //\r
456 // check for "-?"\r
457 //\r
458 Status = gRT->GetTime (&TheTime, NULL);\r
459 if (EFI_ERROR (Status)) {\r
460 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_UEFI_FUNC_WARN), gShellLevel2HiiHandle, L"time", L"gRT->GetTime", Status);\r
461 return (SHELL_DEVICE_ERROR);\r
462 }\r
463\r
464 if (ShellCommandLineGetFlag (Package, L"-?")) {\r
465 ASSERT (FALSE);\r
466 } else if (ShellCommandLineGetRawValue (Package, 2) != NULL) {\r
467 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellLevel2HiiHandle, L"time");\r
468 ShellStatus = SHELL_INVALID_PARAMETER;\r
469 } else {\r
470 //\r
471 // If there are no parameters, then print the current time\r
472 //\r
473 if ( (ShellCommandLineGetRawValue (Package, 1) == NULL)\r
474 && !ShellCommandLineGetFlag (Package, L"-d")\r
475 && !ShellCommandLineGetFlag (Package, L"-tz"))\r
476 {\r
477 //\r
478 // ShellPrintEx the current time\r
479 //\r
480 if (TheTime.TimeZone == EFI_UNSPECIFIED_TIMEZONE) {\r
481 TzMinutes = 0;\r
482 } else {\r
483 TzMinutes = (ABS (TheTime.TimeZone)) % 60;\r
484 }\r
485\r
486 if (TheTime.TimeZone != EFI_UNSPECIFIED_TIMEZONE) {\r
487 ShellPrintHiiEx (\r
488 -1,\r
489 -1,\r
490 NULL,\r
491 STRING_TOKEN (STR_TIME_FORMAT),\r
492 gShellLevel2HiiHandle,\r
493 TheTime.Hour,\r
494 TheTime.Minute,\r
495 TheTime.Second,\r
496 (TheTime.TimeZone > 0 ? L"-" : L"+"),\r
497 ((ABS (TheTime.TimeZone)) / 60),\r
498 TzMinutes\r
499 );\r
500 } else {\r
501 ShellPrintHiiEx (\r
502 -1,\r
503 -1,\r
504 NULL,\r
505 STRING_TOKEN (STR_TIME_FORMAT_LOCAL),\r
506 gShellLevel2HiiHandle,\r
507 TheTime.Hour,\r
508 TheTime.Minute,\r
509 TheTime.Second\r
510 );\r
511 }\r
512\r
513 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_CRLF), gShellLevel2HiiHandle);\r
514 } else if (ShellCommandLineGetFlag (Package, L"-d") && (ShellCommandLineGetValue (Package, L"-d") == NULL)) {\r
515 if (TheTime.TimeZone == EFI_UNSPECIFIED_TIMEZONE) {\r
516 ShellPrintHiiEx (\r
517 -1,\r
518 -1,\r
519 NULL,\r
520 STRING_TOKEN (STR_TIME_FORMAT_LOCAL),\r
521 gShellLevel2HiiHandle,\r
522 TheTime.Hour,\r
523 TheTime.Minute,\r
524 TheTime.Second\r
525 );\r
526 } else {\r
527 TzMinutes = (ABS (TheTime.TimeZone)) % 60;\r
528 ShellPrintHiiEx (\r
529 -1,\r
530 -1,\r
531 NULL,\r
532 STRING_TOKEN (STR_TIME_FORMAT),\r
533 gShellLevel2HiiHandle,\r
534 TheTime.Hour,\r
535 TheTime.Minute,\r
536 TheTime.Second,\r
537 (TheTime.TimeZone > 0 ? L"-" : L"+"),\r
538 ((ABS (TheTime.TimeZone)) / 60),\r
539 TzMinutes\r
540 );\r
541 }\r
542\r
543 switch (TheTime.Daylight) {\r
544 case 0:\r
545 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_TIME_DST0), gShellLevel2HiiHandle);\r
546 break;\r
547 case EFI_TIME_ADJUST_DAYLIGHT:\r
548 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_TIME_DST1), gShellLevel2HiiHandle);\r
549 break;\r
550 case EFI_TIME_IN_DAYLIGHT:\r
551 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_TIME_DST2), gShellLevel2HiiHandle);\r
552 break;\r
553 case EFI_TIME_IN_DAYLIGHT|EFI_TIME_ADJUST_DAYLIGHT:\r
554 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_TIME_DST3), gShellLevel2HiiHandle);\r
555 break;\r
556 default:\r
557 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_UEFI_FUNC_ERROR), gShellLevel2HiiHandle, L"time", L"gRT->GetTime", L"TheTime.Daylight", TheTime.Daylight);\r
558 }\r
559 } else {\r
560 if (PcdGet8 (PcdShellSupportLevel) == 2) {\r
561 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellLevel2HiiHandle, L"time");\r
562 ShellStatus = SHELL_INVALID_PARAMETER;\r
563 } else {\r
564 //\r
565 // perform level 3 operation here.\r
566 //\r
567 if ((TempLocation = ShellCommandLineGetValue (Package, L"-tz")) != NULL) {\r
568 if (gUnicodeCollation->StriColl (gUnicodeCollation, (CHAR16 *)TempLocation, L"_local") == 0) {\r
569 Tz = EFI_UNSPECIFIED_TIMEZONE;\r
570 } else if (TempLocation[0] == L'-') {\r
571 Tz = (INT16)ShellStrToUintn (++TempLocation);\r
572 //\r
573 // When the argument of "time [-tz tz]" is not numeric, ShellStrToUintn() returns "-1".\r
574 // Here we can detect the argument error by checking the return of ShellStrToUintn().\r
575 //\r
576 if (Tz == -1) {\r
577 Tz = 1441; // make it to be out of bounds value\r
578 } else {\r
579 Tz *= (-1); // sign convert\r
580 }\r
581 } else {\r
582 if (TempLocation[0] == L'+') {\r
583 Tz = (INT16)ShellStrToUintn (++TempLocation);\r
584 } else {\r
585 Tz = (INT16)ShellStrToUintn (TempLocation);\r
586 }\r
587\r
588 //\r
589 // Detect the return of ShellStrToUintn() to make sure the argument is valid.\r
590 //\r
591 if (Tz == -1) {\r
592 Tz = 1441; // make it to be out of bounds value\r
593 }\r
594 }\r
595\r
596 if (!((Tz >= -1440) && (Tz <= 1440)) && (Tz != EFI_UNSPECIFIED_TIMEZONE)) {\r
597 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM_VAL), gShellLevel2HiiHandle, L"time", TempLocation, L"-tz");\r
598 ShellStatus = SHELL_INVALID_PARAMETER;\r
599 }\r
600 } else {\r
601 //\r
602 // intentionally out of bounds value will prevent changing it...\r
603 //\r
604 Tz = 1441;\r
605 }\r
606\r
607 TempLocation = ShellCommandLineGetValue (Package, L"-d");\r
608 if (TempLocation != NULL) {\r
609 Daylight = (UINT8)ShellStrToUintn (TempLocation);\r
610 //\r
611 // The argument of "time [-d dl]" is unsigned, if the first character is '-',\r
612 // the argument is incorrect. That's because ShellStrToUintn() will skip past\r
613 // any '-' sign and convert what's next, forgetting the sign is here.\r
614 //\r
615 if (TempLocation[0] == '-') {\r
616 Daylight = 0xff; // make it invalid = will not use\r
617 }\r
618\r
619 if ((Daylight != 0) && (Daylight != 1) && (Daylight != 3)) {\r
620 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM_VAL), gShellLevel2HiiHandle, L"time", TempLocation, L"-d");\r
621 ShellStatus = SHELL_INVALID_PARAMETER;\r
622 }\r
623 } else {\r
624 //\r
625 // invalid = will not use\r
626 //\r
627 Daylight = 0xFF;\r
628 }\r
629\r
630 if (ShellStatus == SHELL_SUCCESS) {\r
631 ShellStatus = CheckAndSetTime (ShellCommandLineGetRawValue (Package, 1), Tz, Daylight);\r
632 if (ShellStatus != SHELL_SUCCESS) {\r
633 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellLevel2HiiHandle, L"time", ShellCommandLineGetRawValue (Package, 1));\r
634 ShellStatus = SHELL_INVALID_PARAMETER;\r
635 }\r
636 }\r
637 }\r
638 }\r
639 }\r
640 }\r
641\r
642 //\r
643 // free the command line package\r
644 //\r
645 ShellCommandLineFreeVarList (Package);\r
646\r
647 //\r
648 // return the status\r
649 //\r
650 return (ShellStatus);\r
651}\r
652\r
653typedef struct {\r
654 INT16 TimeZone;\r
655 EFI_STRING_ID StringId;\r
656} TIME_ZONE_ITEM;\r
657\r
658STATIC CONST SHELL_PARAM_ITEM TimeZoneParamList2[] = {\r
659 { L"-l", TypeFlag },\r
660 { L"-f", TypeFlag },\r
661 { NULL, TypeMax }\r
662};\r
663STATIC CONST SHELL_PARAM_ITEM TimeZoneParamList3[] = {\r
664 { L"-l", TypeFlag },\r
665 { L"-f", TypeFlag },\r
666 { L"-s", TypeTimeValue },\r
667 { NULL, TypeMax }\r
668};\r
669\r
670STATIC CONST TIME_ZONE_ITEM TimeZoneList[] = {\r
671 { 720, STRING_TOKEN (STR_TIMEZONE_M12) },\r
672 { 660, STRING_TOKEN (STR_TIMEZONE_M11) },\r
673 { 600, STRING_TOKEN (STR_TIMEZONE_M10) },\r
674 { 540, STRING_TOKEN (STR_TIMEZONE_M9) },\r
675 { 480, STRING_TOKEN (STR_TIMEZONE_M8) },\r
676 { 420, STRING_TOKEN (STR_TIMEZONE_M7) },\r
677 { 360, STRING_TOKEN (STR_TIMEZONE_M6) },\r
678 { 300, STRING_TOKEN (STR_TIMEZONE_M5) },\r
679 { 270, STRING_TOKEN (STR_TIMEZONE_M430) },\r
680 { 240, STRING_TOKEN (STR_TIMEZONE_M4) },\r
681 { 210, STRING_TOKEN (STR_TIMEZONE_M330) },\r
682 { 180, STRING_TOKEN (STR_TIMEZONE_M3) },\r
683 { 120, STRING_TOKEN (STR_TIMEZONE_M2) },\r
684 { 60, STRING_TOKEN (STR_TIMEZONE_M1) },\r
685 { 0, STRING_TOKEN (STR_TIMEZONE_0) },\r
686 { -60, STRING_TOKEN (STR_TIMEZONE_P1) },\r
687 { -120, STRING_TOKEN (STR_TIMEZONE_P2) },\r
688 { -180, STRING_TOKEN (STR_TIMEZONE_P3) },\r
689 { -210, STRING_TOKEN (STR_TIMEZONE_P330) },\r
690 { -240, STRING_TOKEN (STR_TIMEZONE_P4) },\r
691 { -270, STRING_TOKEN (STR_TIMEZONE_P430) },\r
692 { -300, STRING_TOKEN (STR_TIMEZONE_P5) },\r
693 { -330, STRING_TOKEN (STR_TIMEZONE_P530) },\r
694 { -345, STRING_TOKEN (STR_TIMEZONE_P545) },\r
695 { -360, STRING_TOKEN (STR_TIMEZONE_P6) },\r
696 { -390, STRING_TOKEN (STR_TIMEZONE_P630) },\r
697 { -420, STRING_TOKEN (STR_TIMEZONE_P7) },\r
698 { -480, STRING_TOKEN (STR_TIMEZONE_P8) },\r
699 { -540, STRING_TOKEN (STR_TIMEZONE_P9) },\r
700 { -570, STRING_TOKEN (STR_TIMEZONE_P930) },\r
701 { -600, STRING_TOKEN (STR_TIMEZONE_P10) },\r
702 { -660, STRING_TOKEN (STR_TIMEZONE_P11) },\r
703 { -720, STRING_TOKEN (STR_TIMEZONE_P12) },\r
704 { -780, STRING_TOKEN (STR_TIMEZONE_P13) },\r
705 { -840, STRING_TOKEN (STR_TIMEZONE_P14) },\r
706 { EFI_UNSPECIFIED_TIMEZONE, STRING_TOKEN (STR_TIMEZONE_LOCAL) }\r
707};\r
708\r
709/**\r
710 Verify that the TimeZoneString is valid and if so set that as the current\r
711 timezone.\r
712\r
713 @param[in] TimeZoneString The pointer to a string representation of the timezone.\r
714\r
715 @retval SHELL_INVALID_PARAMETER TimeZoneString was NULL.\r
716 @retval SHELL_INVALID_PARAMETER TimeZoneString was mis-formatted.\r
717 @retval SHELL_SUCCESS The operation was successful.\r
718**/\r
719SHELL_STATUS\r
720CheckAndSetTimeZone (\r
721 IN CONST CHAR16 *TimeZoneString\r
722 )\r
723{\r
724 EFI_TIME TheTime;\r
725 EFI_STATUS Status;\r
726 CHAR16 *TimeZoneCopy;\r
727 CHAR16 *Walker;\r
728 CHAR16 *Walker2;\r
729 UINTN LoopVar;\r
730\r
731 if (TimeZoneString == NULL) {\r
732 return (SHELL_INVALID_PARAMETER);\r
733 }\r
734\r
735 if (gUnicodeCollation->StriColl (gUnicodeCollation, (CHAR16 *)TimeZoneString, L"_local") == 0) {\r
736 Status = gRT->GetTime (&TheTime, NULL);\r
737 if (EFI_ERROR (Status)) {\r
738 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_UEFI_FUNC_WARN), gShellLevel2HiiHandle, L"gRT->GetTime", Status);\r
739 return (SHELL_DEVICE_ERROR);\r
740 }\r
741\r
742 TheTime.TimeZone = EFI_UNSPECIFIED_TIMEZONE;\r
743 Status = gRT->SetTime (&TheTime);\r
744 if (!EFI_ERROR (Status)) {\r
745 return (SHELL_SUCCESS);\r
746 }\r
747\r
748 return (SHELL_INVALID_PARAMETER);\r
749 }\r
750\r
751 if ((TimeZoneString != NULL) && !InternalIsTimeLikeString (TimeZoneString, L':', 1, 1, TRUE)) {\r
752 return (SHELL_INVALID_PARAMETER);\r
753 }\r
754\r
755 Status = gRT->GetTime (&TheTime, NULL);\r
756 if (EFI_ERROR (Status)) {\r
757 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_UEFI_FUNC_WARN), gShellLevel2HiiHandle, L"timezone", L"gRT->GetTime", Status);\r
758 return (SHELL_DEVICE_ERROR);\r
759 }\r
760\r
761 TimeZoneCopy = NULL;\r
762 TimeZoneCopy = StrnCatGrow (&TimeZoneCopy, NULL, TimeZoneString, 0);\r
763 if (TimeZoneCopy == NULL) {\r
764 return (SHELL_OUT_OF_RESOURCES);\r
765 }\r
766\r
767 Walker = TimeZoneCopy;\r
768 Walker2 = StrStr (Walker, L":");\r
769 if ((Walker2 != NULL) && (*Walker2 == L':')) {\r
770 *Walker2 = CHAR_NULL;\r
771 }\r
772\r
773 if (*Walker == L'-') {\r
774 TheTime.TimeZone = (INT16)((ShellStrToUintn (++Walker)) * 60);\r
775 } else {\r
776 TheTime.TimeZone = (INT16)((INT16)(ShellStrToUintn (Walker)) * -60);\r
777 }\r
778\r
779 if (Walker2 != NULL) {\r
780 Walker = Walker2 + 1;\r
781 }\r
782\r
783 if ((Walker != NULL) && (Walker[0] != CHAR_NULL)) {\r
784 if (TheTime.TimeZone < 0) {\r
785 TheTime.TimeZone = (INT16)(TheTime.TimeZone - (UINT8)ShellStrToUintn (Walker));\r
786 } else {\r
787 TheTime.TimeZone = (INT16)(TheTime.TimeZone + (UINT8)ShellStrToUintn (Walker));\r
788 }\r
789 }\r
790\r
791 Status = EFI_INVALID_PARAMETER;\r
792\r
793 for ( LoopVar = 0\r
794 ; LoopVar < sizeof (TimeZoneList) / sizeof (TimeZoneList[0])\r
795 ; LoopVar++\r
796 )\r
797 {\r
798 if (TheTime.TimeZone == TimeZoneList[LoopVar].TimeZone) {\r
799 Status = gRT->SetTime (&TheTime);\r
800 break;\r
801 }\r
802 }\r
803\r
804 FreePool (TimeZoneCopy);\r
805\r
806 if (!EFI_ERROR (Status)) {\r
807 return (SHELL_SUCCESS);\r
808 }\r
809\r
810 return (SHELL_INVALID_PARAMETER);\r
811}\r
812\r
813/**\r
814 Function for 'timezone' command.\r
815\r
816 @param[in] ImageHandle Handle to the Image (NULL if Internal).\r
817 @param[in] SystemTable Pointer to the System Table (NULL if Internal).\r
818**/\r
819SHELL_STATUS\r
820EFIAPI\r
821ShellCommandRunTimeZone (\r
822 IN EFI_HANDLE ImageHandle,\r
823 IN EFI_SYSTEM_TABLE *SystemTable\r
824 )\r
825{\r
826 //\r
827 // non interactive\r
828 //\r
829 EFI_STATUS Status;\r
830 LIST_ENTRY *Package;\r
831 CHAR16 *ProblemParam;\r
832 SHELL_STATUS ShellStatus;\r
833 UINT8 LoopVar;\r
834 EFI_TIME TheTime;\r
835 BOOLEAN Found;\r
836 UINTN TzMinutes;\r
837\r
838 ShellStatus = SHELL_SUCCESS;\r
839 ProblemParam = NULL;\r
840\r
841 //\r
842 // initialize the shell lib (we must be in non-auto-init...)\r
843 //\r
844 Status = ShellInitialize ();\r
845 ASSERT_EFI_ERROR (Status);\r
846\r
847 //\r
848 // parse the command line\r
849 //\r
850 if (PcdGet8 (PcdShellSupportLevel) == 2) {\r
851 Status = ShellCommandLineParse (TimeZoneParamList2, &Package, &ProblemParam, TRUE);\r
852 } else {\r
853 ASSERT (PcdGet8 (PcdShellSupportLevel) == 3);\r
854 Status = ShellCommandLineParseEx (TimeZoneParamList3, &Package, &ProblemParam, TRUE, TRUE);\r
855 }\r
856\r
857 if (EFI_ERROR (Status)) {\r
858 if ((Status == EFI_VOLUME_CORRUPTED) && (ProblemParam != NULL)) {\r
859 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellLevel2HiiHandle, L"timezone", ProblemParam);\r
860 FreePool (ProblemParam);\r
861 ShellStatus = SHELL_INVALID_PARAMETER;\r
862 } else {\r
863 ASSERT (FALSE);\r
864 }\r
865 } else {\r
866 //\r
867 // check for "-?"\r
868 //\r
869 if (ShellCommandLineGetCount (Package) > 1) {\r
870 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellLevel2HiiHandle, L"timezone");\r
871 ShellStatus = SHELL_INVALID_PARAMETER;\r
872 } else if (ShellCommandLineGetFlag (Package, L"-?")) {\r
873 ASSERT (FALSE);\r
874 } else if (ShellCommandLineGetFlag (Package, L"-s")) {\r
875 if ((ShellCommandLineGetFlag (Package, L"-l")) || (ShellCommandLineGetFlag (Package, L"-f"))) {\r
876 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellLevel2HiiHandle, L"timezone", L"-l or -f");\r
877 ShellStatus = SHELL_INVALID_PARAMETER;\r
878 } else {\r
879 ASSERT (PcdGet8 (PcdShellSupportLevel) == 3);\r
880 if (ShellCommandLineGetValue (Package, L"-s") == NULL) {\r
881 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_VALUE), gShellLevel2HiiHandle, L"timezone", L"-s");\r
882 ShellStatus = SHELL_INVALID_PARAMETER;\r
883 } else {\r
884 //\r
885 // Set the time zone\r
886 //\r
887 ShellStatus = CheckAndSetTimeZone (ShellCommandLineGetValue (Package, L"-s"));\r
888 if (ShellStatus != SHELL_SUCCESS) {\r
889 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellLevel2HiiHandle, L"timezone", ShellCommandLineGetValue (Package, L"-s"));\r
890 ShellStatus = SHELL_INVALID_PARAMETER;\r
891 }\r
892 }\r
893 }\r
894 } else if (ShellCommandLineGetFlag (Package, L"-l")) {\r
895 //\r
896 // Print a list of all time zones\r
897 //\r
898 for ( LoopVar = 0\r
899 ; LoopVar < sizeof (TimeZoneList) / sizeof (TimeZoneList[0])\r
900 ; LoopVar++\r
901 )\r
902 {\r
903 ShellPrintHiiEx (-1, -1, NULL, TimeZoneList[LoopVar].StringId, gShellLevel2HiiHandle);\r
904 }\r
905 } else {\r
906 //\r
907 // Get Current Time Zone Info\r
908 //\r
909 Status = gRT->GetTime (&TheTime, NULL);\r
910 if (EFI_ERROR (Status)) {\r
911 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_UEFI_FUNC_WARN), gShellLevel2HiiHandle, L"timezone", L"gRT->GetTime", Status);\r
912 return (SHELL_DEVICE_ERROR);\r
913 }\r
914\r
915 if (TheTime.TimeZone != EFI_UNSPECIFIED_TIMEZONE) {\r
916 Found = FALSE;\r
917 for ( LoopVar = 0\r
918 ; LoopVar < sizeof (TimeZoneList) / sizeof (TimeZoneList[0])\r
919 ; LoopVar++\r
920 )\r
921 {\r
922 if (TheTime.TimeZone == TimeZoneList[LoopVar].TimeZone) {\r
923 if (ShellCommandLineGetFlag (Package, L"-f")) {\r
924 //\r
925 // Print all info about current time zone\r
926 //\r
927 ShellPrintHiiEx (-1, -1, NULL, TimeZoneList[LoopVar].StringId, gShellLevel2HiiHandle);\r
928 } else {\r
929 //\r
930 // Print basic info only\r
931 //\r
932 TzMinutes = (ABS (TheTime.TimeZone)) % 60;\r
933\r
934 ShellPrintHiiEx (\r
935 -1,\r
936 -1,\r
937 NULL,\r
938 STRING_TOKEN (STR_TIMEZONE_SIMPLE),\r
939 gShellLevel2HiiHandle,\r
940 (TheTime.TimeZone > 0 ? L"-" : L"+"),\r
941 (ABS (TheTime.TimeZone)) / 60,\r
942 TzMinutes\r
943 );\r
944 }\r
945\r
946 Found = TRUE;\r
947 break;\r
948 }\r
949 }\r
950\r
951 if (!Found) {\r
952 //\r
953 // Print basic info only\r
954 //\r
955 TzMinutes = (ABS (TheTime.TimeZone)) % 60;\r
956\r
957 ShellPrintHiiEx (\r
958 -1,\r
959 -1,\r
960 NULL,\r
961 STRING_TOKEN (STR_TIMEZONE_SIMPLE),\r
962 gShellLevel2HiiHandle,\r
963 (TheTime.TimeZone > 0 ? L"-" : L"+"),\r
964 (ABS (TheTime.TimeZone)) / 60,\r
965 TzMinutes\r
966 );\r
967\r
968 if (ShellCommandLineGetFlag (Package, L"-f")) {\r
969 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_TIMEZONE_NI), gShellLevel2HiiHandle);\r
970 }\r
971 }\r
972 } else {\r
973 //\r
974 // TimeZone was EFI_UNSPECIFIED_TIMEZONE (local) from GetTime()\r
975 //\r
976 if (ShellCommandLineGetFlag (Package, L"-f")) {\r
977 for ( LoopVar = 0\r
978 ; LoopVar < ARRAY_SIZE (TimeZoneList)\r
979 ; LoopVar++\r
980 )\r
981 {\r
982 if (TheTime.TimeZone == TimeZoneList[LoopVar].TimeZone) {\r
983 //\r
984 // Print all info about current time zone\r
985 //\r
986 ShellPrintHiiEx (-1, -1, NULL, TimeZoneList[LoopVar].StringId, gShellLevel2HiiHandle);\r
987 break;\r
988 }\r
989 }\r
990 } else {\r
991 //\r
992 // Print basic info only\r
993 //\r
994 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_TIMEZONE_SIMPLE_LOCAL), gShellLevel2HiiHandle);\r
995 }\r
996 }\r
997 }\r
998 }\r
999\r
1000 //\r
1001 // free the command line package\r
1002 //\r
1003 ShellCommandLineFreeVarList (Package);\r
1004\r
1005 return (ShellStatus);\r
1006}\r