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