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