Home | History | Annotate | Download | only in UefiShellLevel2CommandsLib
      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 **/
     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 (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 
    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 (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 **/
    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 }
    973