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 - 2014, 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**/ 30BOOLEAN 31InternalIsTimeLikeString ( 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**/ 88SHELL_STATUS 89CheckAndSetDate ( 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**/ 169SHELL_STATUS 170EFIAPI 171ShellCommandRunDate ( 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// 278STATIC CONST SHELL_PARAM_ITEM TimeParamList2[] = { 279 {L"-d", TypeValue}, 280 {NULL, TypeMax} 281 }; 282 283STATIC 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**/ 301SHELL_STATUS 302CheckAndSetTime ( 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**/ 396SHELL_STATUS 397EFIAPI 398ShellCommandRunTime ( 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 (StrniCmp (TempLocation, L"_local", StrLen (TempLocation)) == NULL) { 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 634typedef struct { 635 INT16 TimeZone; 636 EFI_STRING_ID StringId; 637} TIME_ZONE_ITEM; 638 639STATIC CONST SHELL_PARAM_ITEM TimeZoneParamList2[] = { 640 {L"-l", TypeFlag}, 641 {L"-f", TypeFlag}, 642 {NULL, TypeMax} 643 }; 644STATIC 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**/ 700SHELL_STATUS 701CheckAndSetTimeZone ( 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 (StrniCmp (TimeZoneString, L"_local", StrLen (TimeZoneString)) == NULL) { 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**/ 793SHELL_STATUS 794EFIAPI 795ShellCommandRunTimeZone ( 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} 973