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