Home | History | Annotate | Download | only in UefiShellNetwork1CommandsLib
      1 /** @file
      2   The implementation for Shell command ifconfig based on IP4Config2 protocol.
      3 
      4   (C) Copyright 2013-2015 Hewlett-Packard Development Company, L.P.<BR>
      5   Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.<BR>
      6 
      7   This program and the accompanying materials
      8   are licensed and made available under the terms and conditions of the BSD License
      9   which accompanies this distribution.  The full text of the license may be found at
     10   http://opensource.org/licenses/bsd-license.php.
     11 
     12   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     13   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     14 
     15 **/
     16 
     17 #include "UefiShellNetwork1CommandsLib.h"
     18 
     19 typedef enum {
     20   IfConfigOpList     = 1,
     21   IfConfigOpSet      = 2,
     22   IfConfigOpClear    = 3
     23 } IFCONFIG_OPCODE;
     24 
     25 typedef enum {
     26   VarCheckReserved      = -1,
     27   VarCheckOk            = 0,
     28   VarCheckDuplicate,
     29   VarCheckConflict,
     30   VarCheckUnknown,
     31   VarCheckLackValue,
     32   VarCheckOutOfMem
     33 } VAR_CHECK_CODE;
     34 
     35 typedef enum {
     36   FlagTypeSingle         = 0,
     37   FlagTypeNeedVar,
     38   FlagTypeNeedSet,
     39   FlagTypeSkipUnknown
     40 } VAR_CHECK_FLAG_TYPE;
     41 
     42 #define MACADDRMAXSIZE    32
     43 
     44 typedef struct _IFCONFIG_INTERFACE_CB {
     45   EFI_HANDLE                                  NicHandle;
     46   LIST_ENTRY                                  Link;
     47   EFI_IP4_CONFIG2_PROTOCOL                    *IfCfg;
     48   EFI_IP4_CONFIG2_INTERFACE_INFO              *IfInfo;
     49   EFI_IP4_CONFIG2_POLICY                      Policy;
     50   UINT32                                      DnsCnt;
     51   EFI_IPv4_ADDRESS                            DnsAddr[1];
     52 } IFCONFIG_INTERFACE_CB;
     53 
     54 typedef struct _ARG_LIST ARG_LIST;
     55 
     56 struct _ARG_LIST {
     57   ARG_LIST    *Next;
     58   CHAR16      *Arg;
     59 };
     60 
     61 typedef struct _IFCONFIG4_PRIVATE_DATA {
     62   LIST_ENTRY  IfList;
     63 
     64   UINT32      OpCode;
     65   CHAR16      *IfName;
     66   ARG_LIST    *VarArg;
     67 } IFCONFIG_PRIVATE_DATA;
     68 
     69 typedef struct _VAR_CHECK_ITEM{
     70   CHAR16                 *FlagStr;
     71   UINT32                 FlagID;
     72   UINT32                 ConflictMask;
     73   VAR_CHECK_FLAG_TYPE    FlagType;
     74 } VAR_CHECK_ITEM;
     75 
     76 SHELL_PARAM_ITEM    mIfConfigCheckList[] = {
     77   {
     78     L"-b",
     79     TypeFlag
     80   },
     81   {
     82     L"-l",
     83     TypeValue
     84   },
     85   {
     86     L"-r",
     87     TypeValue
     88   },
     89   {
     90     L"-c",
     91     TypeValue
     92   },
     93   {
     94     L"-s",
     95     TypeMaxValue
     96   },
     97   {
     98     NULL,
     99     TypeMax
    100   },
    101 };
    102 
    103 VAR_CHECK_ITEM  mSetCheckList[] = {
    104   {
    105    L"static",
    106     0x00000001,
    107     0x00000001,
    108     FlagTypeSingle
    109   },
    110   {
    111     L"dhcp",
    112     0x00000002,
    113     0x00000001,
    114     FlagTypeSingle
    115   },
    116   {
    117     L"dns",
    118     0x00000008,
    119     0x00000004,
    120     FlagTypeSingle
    121   },
    122   {
    123     NULL,
    124     0x0,
    125     0x0,
    126     FlagTypeSkipUnknown
    127   },
    128 };
    129 
    130 STATIC CONST CHAR16 PermanentString[10] = L"PERMANENT";
    131 
    132 /**
    133   Free the ARG_LIST.
    134 
    135   @param List Pointer to ARG_LIST to free.
    136 **/
    137 VOID
    138 FreeArgList (
    139   ARG_LIST       *List
    140 )
    141 {
    142   ARG_LIST       *Next;
    143   while (List->Next != NULL) {
    144     Next = List->Next;
    145     FreePool (List);
    146     List = Next;
    147   }
    148 
    149   FreePool (List);
    150 }
    151 
    152 /**
    153   Split a string with specified separator and save the substring to a list.
    154 
    155   @param[in]    String       The pointer of the input string.
    156   @param[in]    Separator    The specified separator.
    157 
    158   @return The pointer of headnode of ARG_LIST.
    159 
    160 **/
    161 ARG_LIST *
    162 SplitStrToList (
    163   IN CONST CHAR16    *String,
    164   IN CHAR16          Separator
    165   )
    166 {
    167   CHAR16      *Str;
    168   CHAR16      *ArgStr;
    169   ARG_LIST    *ArgList;
    170   ARG_LIST    *ArgNode;
    171 
    172   if (*String == L'\0') {
    173     return NULL;
    174   }
    175 
    176   //
    177   // Copy the CONST string to a local copy.
    178   //
    179   Str = AllocateCopyPool (StrSize (String), String);
    180   if (Str == NULL) {
    181     return NULL;
    182   }
    183   ArgStr  = Str;
    184 
    185   //
    186   // init a node for the list head.
    187   //
    188   ArgNode = (ARG_LIST *) AllocateZeroPool (sizeof (ARG_LIST));
    189   if (ArgNode == NULL) {
    190     return NULL;
    191   }
    192   ArgList = ArgNode;
    193 
    194   //
    195   // Split the local copy and save in the list node.
    196   //
    197   while (*Str != L'\0') {
    198     if (*Str == Separator) {
    199       *Str          = L'\0';
    200       ArgNode->Arg  = ArgStr;
    201       ArgStr        = Str + 1;
    202       ArgNode->Next = (ARG_LIST *) AllocateZeroPool (sizeof (ARG_LIST));
    203       if (ArgNode->Next == NULL) {
    204         //
    205         // Free the local copy of string stored in the first node
    206         //
    207         FreePool (ArgList->Arg);
    208         FreeArgList (ArgList);
    209         return NULL;
    210       }
    211       ArgNode = ArgNode->Next;
    212     }
    213 
    214     Str++;
    215   }
    216 
    217   ArgNode->Arg  = ArgStr;
    218   ArgNode->Next = NULL;
    219 
    220   return ArgList;
    221 }
    222 
    223 /**
    224   Check the correctness of input Args with '-s' option.
    225 
    226   @param[in]    CheckList    The pointer of VAR_CHECK_ITEM array.
    227   @param[in]    Name         The pointer of input arg.
    228   @param[in]    Init         The switch to execute the check.
    229 
    230   @return   VarCheckOk          Valid parameter or Initialize check successfully.
    231   @return   VarCheckDuplicate   Duplicated parameter happened.
    232   @return   VarCheckConflict    Conflicted parameter happened
    233   @return   VarCheckUnknown     Unknown parameter.
    234 
    235 **/
    236 VAR_CHECK_CODE
    237 IfConfigRetriveCheckListByName(
    238   IN VAR_CHECK_ITEM    *CheckList,
    239   IN CHAR16            *Name,
    240   IN BOOLEAN           Init
    241 )
    242 {
    243   STATIC UINT32     CheckDuplicate;
    244   STATIC UINT32     CheckConflict;
    245   VAR_CHECK_CODE    RtCode;
    246   UINT32            Index;
    247   VAR_CHECK_ITEM    Arg;
    248 
    249   if (Init) {
    250     CheckDuplicate = 0;
    251     CheckConflict  = 0;
    252     return VarCheckOk;
    253   }
    254 
    255   RtCode  = VarCheckOk;
    256   Index   = 0;
    257   Arg     = CheckList[Index];
    258 
    259   //
    260   // Check the Duplicated/Conflicted/Unknown input Args.
    261   //
    262   while (Arg.FlagStr != NULL) {
    263     if (StrCmp (Arg.FlagStr, Name) == 0) {
    264 
    265       if (CheckDuplicate & Arg.FlagID) {
    266         RtCode = VarCheckDuplicate;
    267         break;
    268       }
    269 
    270       if (CheckConflict & Arg.ConflictMask) {
    271         RtCode = VarCheckConflict;
    272         break;
    273       }
    274 
    275       CheckDuplicate |= Arg.FlagID;
    276       CheckConflict  |= Arg.ConflictMask;
    277       break;
    278     }
    279 
    280     Arg = CheckList[++Index];
    281   }
    282 
    283   if (Arg.FlagStr == NULL) {
    284     RtCode = VarCheckUnknown;
    285   }
    286 
    287   return RtCode;
    288 }
    289 
    290 /**
    291   The notify function of create event when performing a manual config.
    292 
    293   @param[in]    Event        The event this notify function registered to.
    294   @param[in]    Context      Pointer to the context data registered to the event.
    295 
    296 **/
    297 VOID
    298 EFIAPI
    299 IfConfigManualAddressNotify (
    300   IN EFI_EVENT    Event,
    301   IN VOID         *Context
    302   )
    303 {
    304   *((BOOLEAN *) Context) = TRUE;
    305 }
    306 
    307 /**
    308   Print MAC address.
    309 
    310   @param[in]    Node    The pointer of MAC address buffer.
    311   @param[in]    Size    The size of MAC address buffer.
    312 
    313 **/
    314 VOID
    315 IfConfigPrintMacAddr (
    316   IN UINT8     *Node,
    317   IN UINT32    Size
    318   )
    319 {
    320   UINTN    Index;
    321 
    322   ASSERT (Size <= MACADDRMAXSIZE);
    323 
    324   for (Index = 0; Index < Size; Index++) {
    325     ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_INFO_MAC_ADDR_BODY), gShellNetwork1HiiHandle, Node[Index]);
    326     if (Index + 1 < Size) {
    327       ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_INFO_COLON), gShellNetwork1HiiHandle);
    328     }
    329   }
    330 
    331   ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_INFO_NEWLINE), gShellNetwork1HiiHandle);
    332 }
    333 
    334 
    335 /**
    336   The get current status of all handles.
    337 
    338   @param[in]   IfName         The pointer of IfName(interface name).
    339   @param[in]   IfList         The pointer of IfList(interface list).
    340 
    341   @retval EFI_SUCCESS    The get status processed successfully.
    342   @retval others         The get status process failed.
    343 
    344 **/
    345 EFI_STATUS
    346 IfConfigGetInterfaceInfo (
    347   IN CHAR16        *IfName,
    348   IN LIST_ENTRY    *IfList
    349   )
    350 {
    351   EFI_STATUS                       Status;
    352   UINTN                            HandleIndex;
    353   UINTN                            HandleNum;
    354   EFI_HANDLE                       *HandleBuffer;
    355   EFI_IP4_CONFIG2_PROTOCOL         *Ip4Cfg2;
    356   EFI_IP4_CONFIG2_INTERFACE_INFO   *IfInfo;
    357   IFCONFIG_INTERFACE_CB            *IfCb;
    358   UINTN                            DataSize;
    359 
    360   HandleBuffer = NULL;
    361   HandleNum    = 0;
    362 
    363   IfInfo       = NULL;
    364   IfCb         = NULL;
    365 
    366   //
    367   // Locate all the handles with ip4 service binding protocol.
    368   //
    369   Status = gBS->LocateHandleBuffer (
    370                   ByProtocol,
    371                   &gEfiIp4ServiceBindingProtocolGuid,
    372                   NULL,
    373                   &HandleNum,
    374                   &HandleBuffer
    375                  );
    376   if (EFI_ERROR (Status) || (HandleNum == 0)) {
    377     return Status;
    378   }
    379 
    380   //
    381   // Enumerate all handles that installed with ip4 service binding protocol.
    382   //
    383   for (HandleIndex = 0; HandleIndex < HandleNum; HandleIndex++) {
    384     IfCb      = NULL;
    385     IfInfo    = NULL;
    386     DataSize  = 0;
    387 
    388     //
    389     // Ip4config protocol and ip4 service binding protocol are installed
    390     // on the same handle.
    391     //
    392     ASSERT (HandleBuffer != NULL);
    393     Status = gBS->HandleProtocol (
    394                     HandleBuffer[HandleIndex],
    395                     &gEfiIp4Config2ProtocolGuid,
    396                     (VOID **) &Ip4Cfg2
    397                     );
    398 
    399     if (EFI_ERROR (Status)) {
    400       goto ON_ERROR;
    401     }
    402 
    403     //
    404     // Get the interface information size.
    405     //
    406     Status = Ip4Cfg2->GetData (
    407                        Ip4Cfg2,
    408                        Ip4Config2DataTypeInterfaceInfo,
    409                        &DataSize,
    410                        NULL
    411                        );
    412 
    413     if (Status != EFI_BUFFER_TOO_SMALL) {
    414       goto ON_ERROR;
    415     }
    416 
    417     IfInfo = AllocateZeroPool (DataSize);
    418 
    419     if (IfInfo == NULL) {
    420       Status = EFI_OUT_OF_RESOURCES;
    421       goto ON_ERROR;
    422     }
    423 
    424     //
    425     // Get the interface info.
    426     //
    427     Status = Ip4Cfg2->GetData (
    428                        Ip4Cfg2,
    429                        Ip4Config2DataTypeInterfaceInfo,
    430                        &DataSize,
    431                        IfInfo
    432                        );
    433 
    434     if (EFI_ERROR (Status)) {
    435       goto ON_ERROR;
    436     }
    437 
    438     //
    439     // Check the interface name if required.
    440     //
    441     if ((IfName != NULL) && (StrCmp (IfName, IfInfo->Name) != 0)) {
    442       FreePool (IfInfo);
    443       continue;
    444     }
    445 
    446     DataSize = 0;
    447 
    448     //
    449     // Get the size of dns server list.
    450     //
    451     Status = Ip4Cfg2->GetData (
    452                        Ip4Cfg2,
    453                        Ip4Config2DataTypeDnsServer,
    454                        &DataSize,
    455                        NULL
    456                        );
    457 
    458     if ((Status != EFI_BUFFER_TOO_SMALL) && (Status != EFI_NOT_FOUND)) {
    459       goto ON_ERROR;
    460     }
    461 
    462     IfCb = AllocateZeroPool (sizeof (IFCONFIG_INTERFACE_CB) + DataSize);
    463 
    464     if (IfCb == NULL) {
    465       Status = EFI_OUT_OF_RESOURCES;
    466       goto ON_ERROR;
    467     }
    468 
    469     IfCb->NicHandle = HandleBuffer[HandleIndex];
    470     IfCb->IfInfo    = IfInfo;
    471     IfCb->IfCfg     = Ip4Cfg2;
    472     IfCb->DnsCnt    = (UINT32) (DataSize / sizeof (EFI_IPv4_ADDRESS));
    473 
    474     //
    475     // Get the dns server list if has.
    476     //
    477     if (DataSize > 0) {
    478       Status = Ip4Cfg2->GetData (
    479                          Ip4Cfg2,
    480                          Ip4Config2DataTypeDnsServer,
    481                          &DataSize,
    482                          IfCb->DnsAddr
    483                          );
    484 
    485       if (EFI_ERROR (Status)) {
    486         goto ON_ERROR;
    487       }
    488     }
    489 
    490     //
    491     // Get the config policy.
    492     //
    493     DataSize = sizeof (EFI_IP4_CONFIG2_POLICY);
    494     Status   = Ip4Cfg2->GetData (
    495                          Ip4Cfg2,
    496                          Ip4Config2DataTypePolicy,
    497                          &DataSize,
    498                          &IfCb->Policy
    499                          );
    500 
    501     if (EFI_ERROR (Status)) {
    502       goto ON_ERROR;
    503     }
    504 
    505     InsertTailList (IfList, &IfCb->Link);
    506 
    507     if ((IfName != NULL) && (StrCmp (IfName, IfInfo->Name) == 0)) {
    508       //
    509       // Only need the appointed interface, keep the allocated buffer.
    510       //
    511       IfCb   = NULL;
    512       IfInfo = NULL;
    513       break;
    514     }
    515   }
    516 
    517   if (HandleBuffer != NULL) {
    518     FreePool (HandleBuffer);
    519   }
    520 
    521   return EFI_SUCCESS;
    522 
    523 ON_ERROR:
    524 
    525   if (IfInfo != NULL) {
    526     FreePool (IfInfo);
    527   }
    528 
    529   if (IfCb != NULL) {
    530     FreePool (IfCb);
    531   }
    532 
    533   return Status;
    534 }
    535 
    536 /**
    537   The list process of the ifconfig command.
    538 
    539   @param[in]   IfList    The pointer of IfList(interface list).
    540 
    541   @retval SHELL_SUCCESS  The ifconfig command list processed successfully.
    542   @retval others         The ifconfig command list process failed.
    543 
    544 **/
    545 SHELL_STATUS
    546 IfConfigShowInterfaceInfo (
    547   IN LIST_ENTRY    *IfList
    548   )
    549 {
    550   LIST_ENTRY                   *Entry;
    551   LIST_ENTRY                   *Next;
    552   IFCONFIG_INTERFACE_CB        *IfCb;
    553   BOOLEAN                       MediaPresent;
    554   EFI_IPv4_ADDRESS              Gateway;
    555   UINT32                        Index;
    556 
    557   MediaPresent = TRUE;
    558 
    559   if (IsListEmpty (IfList)) {
    560     ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_INVALID_INTERFACE), gShellNetwork1HiiHandle);
    561   }
    562 
    563   //
    564   // Go through the interface list.
    565   //
    566   NET_LIST_FOR_EACH_SAFE (Entry, Next, IfList) {
    567     IfCb = NET_LIST_USER_STRUCT (Entry, IFCONFIG_INTERFACE_CB, Link);
    568 
    569     ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_INFO_BREAK), gShellNetwork1HiiHandle);
    570 
    571     //
    572     // Print interface name.
    573     //
    574     ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_INFO_IF_NAME), gShellNetwork1HiiHandle, IfCb->IfInfo->Name);
    575 
    576     //
    577     // Get Media State.
    578     //
    579     NetLibDetectMedia (IfCb->NicHandle, &MediaPresent);
    580     if (!MediaPresent) {
    581       ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_INFO_MEDIA_STATE), gShellNetwork1HiiHandle, L"Media disconnected");
    582     } else {
    583       ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_INFO_MEDIA_STATE), gShellNetwork1HiiHandle, L"Media present");
    584     }
    585 
    586     //
    587     // Print interface config policy.
    588     //
    589     if (IfCb->Policy == Ip4Config2PolicyDhcp) {
    590       ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_INFO_POLICY_DHCP), gShellNetwork1HiiHandle);
    591     } else {
    592       ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_INFO_POLICY_MAN), gShellNetwork1HiiHandle);
    593     }
    594 
    595     //
    596     // Print mac address of the interface.
    597     //
    598     ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_INFO_MAC_ADDR_HEAD), gShellNetwork1HiiHandle);
    599 
    600     IfConfigPrintMacAddr (
    601       IfCb->IfInfo->HwAddress.Addr,
    602       IfCb->IfInfo->HwAddressSize
    603       );
    604 
    605     //
    606     // Print IPv4 address list of the interface.
    607     //
    608     ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_INFO_IP_ADDR_HEAD), gShellNetwork1HiiHandle);
    609 
    610     ShellPrintHiiEx(
    611       -1,
    612       -1,
    613       NULL,
    614       STRING_TOKEN (STR_IFCONFIG_INFO_IP_ADDR_BODY),
    615       gShellNetwork1HiiHandle,
    616       (UINTN)IfCb->IfInfo->StationAddress.Addr[0],
    617       (UINTN)IfCb->IfInfo->StationAddress.Addr[1],
    618       (UINTN)IfCb->IfInfo->StationAddress.Addr[2],
    619       (UINTN)IfCb->IfInfo->StationAddress.Addr[3]
    620       );
    621 
    622     //
    623     // Print subnet mask list of the interface.
    624     //
    625     ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_INFO_SUBNET_MASK_HEAD), gShellNetwork1HiiHandle);
    626 
    627     ShellPrintHiiEx(
    628       -1,
    629       -1,
    630       NULL,
    631       STRING_TOKEN (STR_IFCONFIG_INFO_IP_ADDR_BODY),
    632       gShellNetwork1HiiHandle,
    633       (UINTN)IfCb->IfInfo->SubnetMask.Addr[0],
    634       (UINTN)IfCb->IfInfo->SubnetMask.Addr[1],
    635       (UINTN)IfCb->IfInfo->SubnetMask.Addr[2],
    636       (UINTN)IfCb->IfInfo->SubnetMask.Addr[3]
    637       );
    638 
    639     //
    640     // Print default gateway of the interface.
    641     //
    642     ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_INFO_GATEWAY_HEAD), gShellNetwork1HiiHandle);
    643 
    644     ZeroMem (&Gateway, sizeof (EFI_IPv4_ADDRESS));
    645 
    646     for (Index = 0; Index < IfCb->IfInfo->RouteTableSize; Index++) {
    647       if ((CompareMem (&IfCb->IfInfo->RouteTable[Index].SubnetAddress, &mZeroIp4Addr, sizeof (EFI_IPv4_ADDRESS)) == 0) &&
    648           (CompareMem (&IfCb->IfInfo->RouteTable[Index].SubnetMask   , &mZeroIp4Addr, sizeof (EFI_IPv4_ADDRESS)) == 0) ){
    649         CopyMem (&Gateway, &IfCb->IfInfo->RouteTable[Index].GatewayAddress, sizeof (EFI_IPv4_ADDRESS));
    650       }
    651     }
    652 
    653     ShellPrintHiiEx(
    654       -1,
    655       -1,
    656       NULL,
    657       STRING_TOKEN (STR_IFCONFIG_INFO_IP_ADDR_BODY),
    658       gShellNetwork1HiiHandle,
    659       (UINTN)Gateway.Addr[0],
    660       (UINTN)Gateway.Addr[1],
    661       (UINTN)Gateway.Addr[2],
    662       (UINTN)Gateway.Addr[3]
    663       );
    664 
    665     //
    666     // Print route table entry.
    667     //
    668     ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_IFCONFIG_ROUTES_SIZE), gShellNetwork1HiiHandle, IfCb->IfInfo->RouteTableSize);
    669 
    670     for (Index = 0; Index < IfCb->IfInfo->RouteTableSize; Index++) {
    671       ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_IFCONFIG_ROUTES_ENTRY_INDEX), gShellNetwork1HiiHandle, Index);
    672 
    673       ShellPrintHiiEx(
    674         -1,
    675         -1,
    676         NULL,
    677         STRING_TOKEN (STR_IFCONFIG_SHOW_IP_ADDR),
    678         gShellNetwork1HiiHandle,
    679         L"Subnet ",
    680         (UINTN)IfCb->IfInfo->RouteTable[Index].SubnetAddress.Addr[0],
    681         (UINTN)IfCb->IfInfo->RouteTable[Index].SubnetAddress.Addr[1],
    682         (UINTN)IfCb->IfInfo->RouteTable[Index].SubnetAddress.Addr[2],
    683         (UINTN)IfCb->IfInfo->RouteTable[Index].SubnetAddress.Addr[3]
    684         );
    685 
    686       ShellPrintHiiEx(
    687         -1,
    688         -1,
    689         NULL,
    690         STRING_TOKEN (STR_IFCONFIG_SHOW_IP_ADDR),
    691         gShellNetwork1HiiHandle,
    692         L"Netmask",
    693         (UINTN)IfCb->IfInfo->RouteTable[Index].SubnetMask.Addr[0],
    694         (UINTN)IfCb->IfInfo->RouteTable[Index].SubnetMask.Addr[1],
    695         (UINTN)IfCb->IfInfo->RouteTable[Index].SubnetMask.Addr[2],
    696         (UINTN)IfCb->IfInfo->RouteTable[Index].SubnetMask.Addr[3]
    697         );
    698 
    699       ShellPrintHiiEx(
    700         -1,
    701         -1,
    702         NULL,
    703         STRING_TOKEN (STR_IFCONFIG_SHOW_IP_ADDR),
    704         gShellNetwork1HiiHandle,
    705         L"Gateway",
    706         (UINTN)IfCb->IfInfo->RouteTable[Index].GatewayAddress.Addr[0],
    707         (UINTN)IfCb->IfInfo->RouteTable[Index].GatewayAddress.Addr[1],
    708         (UINTN)IfCb->IfInfo->RouteTable[Index].GatewayAddress.Addr[2],
    709         (UINTN)IfCb->IfInfo->RouteTable[Index].GatewayAddress.Addr[3]
    710         );
    711     }
    712 
    713     //
    714     // Print dns server addresses list of the interface if has.
    715     //
    716     ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_INFO_DNS_ADDR_HEAD), gShellNetwork1HiiHandle);
    717 
    718     for (Index = 0; Index < IfCb->DnsCnt; Index++) {
    719       ShellPrintHiiEx(
    720         -1,
    721         -1,
    722         NULL,
    723         STRING_TOKEN (STR_IFCONFIG_INFO_DNS_ADDR_BODY),
    724         gShellNetwork1HiiHandle,
    725         (UINTN) IfCb->DnsAddr[Index].Addr[0],
    726         (UINTN) IfCb->DnsAddr[Index].Addr[1],
    727         (UINTN) IfCb->DnsAddr[Index].Addr[2],
    728         (UINTN) IfCb->DnsAddr[Index].Addr[3]
    729         );
    730 
    731       ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_INFO_NEWLINE), gShellNetwork1HiiHandle);
    732     }
    733   }
    734 
    735   ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_INFO_BREAK), gShellNetwork1HiiHandle);
    736 
    737   return SHELL_SUCCESS;
    738 }
    739 
    740 /**
    741   The clean process of the ifconfig command to clear interface info.
    742 
    743   @param[in]   IfList    The pointer of IfList(interface list).
    744   @param[in]   IfName    The pointer of interface name.
    745 
    746   @retval SHELL_SUCCESS  The ifconfig command clean processed successfully.
    747   @retval others         The ifconfig command clean process failed.
    748 
    749 **/
    750 SHELL_STATUS
    751 IfConfigClearInterfaceInfo (
    752   IN LIST_ENTRY    *IfList,
    753   IN CHAR16        *IfName
    754   )
    755 {
    756   EFI_STATUS                Status;
    757   SHELL_STATUS              ShellStatus;
    758   LIST_ENTRY                *Entry;
    759   LIST_ENTRY                *Next;
    760   IFCONFIG_INTERFACE_CB     *IfCb;
    761   EFI_IP4_CONFIG2_POLICY    Policy;
    762 
    763   Status = EFI_SUCCESS;
    764   ShellStatus = SHELL_SUCCESS;
    765 
    766   if (IsListEmpty (IfList)) {
    767     ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_INVALID_INTERFACE), gShellNetwork1HiiHandle);
    768   }
    769 
    770   //
    771   // Go through the interface list.
    772   // If the interface name is specified, DHCP DORA process will be
    773   // triggered by the policy transition (static -> dhcp).
    774   //
    775   NET_LIST_FOR_EACH_SAFE (Entry, Next, IfList) {
    776     IfCb = NET_LIST_USER_STRUCT (Entry, IFCONFIG_INTERFACE_CB, Link);
    777 
    778     if ((IfName != NULL) && (StrCmp (IfName, IfCb->IfInfo->Name) == 0)) {
    779       Policy = Ip4Config2PolicyStatic;
    780 
    781       Status = IfCb->IfCfg->SetData (
    782                               IfCb->IfCfg,
    783                               Ip4Config2DataTypePolicy,
    784                               sizeof (EFI_IP4_CONFIG2_POLICY),
    785                               &Policy
    786                               );
    787       if (EFI_ERROR (Status)) {
    788         ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_ERR_AD), gShellNetwork1HiiHandle, L"ifconfig");
    789         ShellStatus = SHELL_ACCESS_DENIED;
    790         break;
    791       }
    792     }
    793 
    794     Policy = Ip4Config2PolicyDhcp;
    795 
    796     Status = IfCb->IfCfg->SetData (
    797                             IfCb->IfCfg,
    798                             Ip4Config2DataTypePolicy,
    799                             sizeof (EFI_IP4_CONFIG2_POLICY),
    800                             &Policy
    801                             );
    802     if (EFI_ERROR (Status)) {
    803       ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_ERR_AD), gShellNetwork1HiiHandle, L"ifconfig");
    804       ShellStatus = SHELL_ACCESS_DENIED;
    805       break;
    806     }
    807   }
    808 
    809   return ShellStatus;
    810 }
    811 
    812 /**
    813   The set process of the ifconfig command.
    814 
    815   @param[in]   IfList    The pointer of IfList(interface list).
    816   @param[in]   VarArg    The pointer of ARG_LIST(Args with "-s" option).
    817 
    818   @retval SHELL_SUCCESS  The ifconfig command set processed successfully.
    819   @retval others         The ifconfig command set process failed.
    820 
    821 **/
    822 SHELL_STATUS
    823 IfConfigSetInterfaceInfo (
    824   IN LIST_ENTRY    *IfList,
    825   IN ARG_LIST      *VarArg
    826   )
    827 {
    828   EFI_STATUS                       Status;
    829   SHELL_STATUS                     ShellStatus;
    830   IFCONFIG_INTERFACE_CB            *IfCb;
    831   VAR_CHECK_CODE                   CheckCode;
    832   EFI_EVENT                        TimeOutEvt;
    833   EFI_EVENT                        MappedEvt;
    834   BOOLEAN                          IsAddressOk;
    835 
    836   EFI_IP4_CONFIG2_POLICY           Policy;
    837   EFI_IP4_CONFIG2_MANUAL_ADDRESS   ManualAddress;
    838   UINTN                            DataSize;
    839   EFI_IPv4_ADDRESS                 Gateway;
    840   EFI_IPv4_ADDRESS                 *Dns;
    841   ARG_LIST                         *Tmp;
    842   UINTN                            Index;
    843 
    844   CONST CHAR16* TempString;
    845 
    846   Dns = NULL;
    847 
    848   if (IsListEmpty (IfList)) {
    849     ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_INVALID_INTERFACE), gShellNetwork1HiiHandle);
    850     return SHELL_INVALID_PARAMETER;
    851   }
    852 
    853   //
    854   // Make sure to set only one interface each time.
    855   //
    856   IfCb   = NET_LIST_USER_STRUCT (IfList->ForwardLink, IFCONFIG_INTERFACE_CB, Link);
    857   Status = EFI_SUCCESS;
    858   ShellStatus = SHELL_SUCCESS;
    859 
    860   //
    861   // Initialize check list mechanism.
    862   //
    863   CheckCode = IfConfigRetriveCheckListByName(
    864                 NULL,
    865                 NULL,
    866                 TRUE
    867                 );
    868 
    869   //
    870   // Create events & timers for asynchronous settings.
    871   //
    872   Status = gBS->CreateEvent (
    873                   EVT_TIMER,
    874                   TPL_CALLBACK,
    875                   NULL,
    876                   NULL,
    877                   &TimeOutEvt
    878                   );
    879   if (EFI_ERROR (Status)) {
    880     ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_ERR_AD), gShellNetwork1HiiHandle, L"ifconfig");
    881     ShellStatus = SHELL_ACCESS_DENIED;
    882     goto ON_EXIT;
    883   }
    884 
    885   Status = gBS->CreateEvent (
    886                   EVT_NOTIFY_SIGNAL,
    887                   TPL_NOTIFY,
    888                   IfConfigManualAddressNotify,
    889                   &IsAddressOk,
    890                   &MappedEvt
    891                   );
    892   if (EFI_ERROR (Status)) {
    893     ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_ERR_AD), gShellNetwork1HiiHandle, L"ifconfig");
    894     ShellStatus = SHELL_ACCESS_DENIED;
    895     goto ON_EXIT;
    896   }
    897 
    898   //
    899   // Parse the setting variables.
    900   //
    901   while (VarArg != NULL) {
    902     //
    903     // Check invalid parameters (duplication & unknown & conflict).
    904     //
    905     CheckCode = IfConfigRetriveCheckListByName(
    906                   mSetCheckList,
    907                   VarArg->Arg,
    908                   FALSE
    909                   );
    910 
    911     if (VarCheckOk != CheckCode) {
    912       switch (CheckCode) {
    913         case VarCheckDuplicate:
    914           ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_DUPLICATE_COMMAND), gShellNetwork1HiiHandle, VarArg->Arg);
    915           break;
    916 
    917         case VarCheckConflict:
    918           ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_CONFLICT_COMMAND), gShellNetwork1HiiHandle, VarArg->Arg);
    919           break;
    920 
    921         case VarCheckUnknown:
    922           //
    923           // To handle unsupported option.
    924           //
    925           TempString = PermanentString;
    926           if (StringNoCaseCompare(&VarArg->Arg, &TempString) == 0) {
    927             ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_IFCONFIG_UNSUPPORTED_OPTION), gShellNetwork1HiiHandle, PermanentString);
    928             goto ON_EXIT;
    929           }
    930 
    931           //
    932           // To handle unknown option.
    933           //
    934           ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_UNKNOWN_COMMAND), gShellNetwork1HiiHandle, VarArg->Arg);
    935           break;
    936 
    937         default:
    938           break;
    939       }
    940 
    941       VarArg = VarArg->Next;
    942       continue;
    943     }
    944 
    945     //
    946     // Process valid variables.
    947     //
    948     if (StrCmp(VarArg->Arg, L"dhcp") == 0) {
    949       //
    950       // Set dhcp config policy
    951       //
    952       Policy = Ip4Config2PolicyDhcp;
    953       Status = IfCb->IfCfg->SetData (
    954                               IfCb->IfCfg,
    955                               Ip4Config2DataTypePolicy,
    956                               sizeof (EFI_IP4_CONFIG2_POLICY),
    957                               &Policy
    958                               );
    959       if (EFI_ERROR(Status)) {
    960         ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_ERR_AD), gShellNetwork1HiiHandle, L"ifconfig");
    961         ShellStatus = SHELL_ACCESS_DENIED;
    962         goto ON_EXIT;
    963       }
    964 
    965       VarArg= VarArg->Next;
    966 
    967     } else if (StrCmp (VarArg->Arg, L"static") == 0) {
    968       VarArg= VarArg->Next;
    969       if (VarArg == NULL) {
    970         ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_LACK_COMMAND), gShellNetwork1HiiHandle);
    971         ShellStatus = SHELL_INVALID_PARAMETER;
    972         goto ON_EXIT;
    973       }
    974 
    975       ZeroMem (&ManualAddress, sizeof (ManualAddress));
    976 
    977       //
    978       // Get manual IP address.
    979       //
    980       Status = NetLibStrToIp4 (VarArg->Arg, &ManualAddress.Address);
    981       if (EFI_ERROR(Status)) {
    982         ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_IFCONFIG_INVALID_IPADDRESS), gShellNetwork1HiiHandle, VarArg->Arg);
    983         ShellStatus = SHELL_INVALID_PARAMETER;
    984         goto ON_EXIT;
    985       }
    986 
    987       //
    988       // Get subnetmask.
    989       //
    990       VarArg = VarArg->Next;
    991       if (VarArg == NULL) {
    992         ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_LACK_COMMAND), gShellNetwork1HiiHandle);
    993         ShellStatus = SHELL_INVALID_PARAMETER;
    994         goto ON_EXIT;
    995       }
    996 
    997       Status = NetLibStrToIp4 (VarArg->Arg, &ManualAddress.SubnetMask);
    998       if (EFI_ERROR(Status)) {
    999         ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_IFCONFIG_INVALID_IPADDRESS), gShellNetwork1HiiHandle, VarArg->Arg);
   1000         ShellStatus = SHELL_INVALID_PARAMETER;
   1001         goto ON_EXIT;
   1002       }
   1003 
   1004       //
   1005       // Get gateway.
   1006       //
   1007       VarArg = VarArg->Next;
   1008       if (VarArg == NULL) {
   1009         ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_LACK_COMMAND), gShellNetwork1HiiHandle);
   1010         ShellStatus = SHELL_INVALID_PARAMETER;
   1011         goto ON_EXIT;
   1012       }
   1013 
   1014       Status = NetLibStrToIp4 (VarArg->Arg, &Gateway);
   1015       if (EFI_ERROR(Status)) {
   1016         ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_IFCONFIG_INVALID_IPADDRESS), gShellNetwork1HiiHandle, VarArg->Arg);
   1017         ShellStatus = SHELL_INVALID_PARAMETER;
   1018         goto ON_EXIT;
   1019       }
   1020 
   1021       //
   1022       // Set manual config policy.
   1023       //
   1024       Policy = Ip4Config2PolicyStatic;
   1025       Status = IfCb->IfCfg->SetData (
   1026                               IfCb->IfCfg,
   1027                               Ip4Config2DataTypePolicy,
   1028                               sizeof (EFI_IP4_CONFIG2_POLICY),
   1029                               &Policy
   1030                               );
   1031       if (EFI_ERROR(Status)) {
   1032         ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_ERR_AD), gShellNetwork1HiiHandle, L"ifconfig");
   1033         ShellStatus = SHELL_ACCESS_DENIED;
   1034         goto ON_EXIT;
   1035       }
   1036 
   1037       //
   1038       // Set Manual Address.
   1039       //
   1040       IsAddressOk = FALSE;
   1041 
   1042       Status = IfCb->IfCfg->RegisterDataNotify (
   1043                               IfCb->IfCfg,
   1044                               Ip4Config2DataTypeManualAddress,
   1045                               MappedEvt
   1046                               );
   1047       if (EFI_ERROR (Status)) {
   1048         ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_SET_ADDR_FAILED), gShellNetwork1HiiHandle, Status);
   1049         ShellStatus = SHELL_ACCESS_DENIED;
   1050         goto ON_EXIT;
   1051       }
   1052 
   1053       DataSize = sizeof (EFI_IP4_CONFIG2_MANUAL_ADDRESS);
   1054 
   1055       Status = IfCb->IfCfg->SetData (
   1056                               IfCb->IfCfg,
   1057                               Ip4Config2DataTypeManualAddress,
   1058                               DataSize,
   1059                               &ManualAddress
   1060                               );
   1061 
   1062       if (Status == EFI_NOT_READY) {
   1063         gBS->SetTimer (TimeOutEvt, TimerRelative, 50000000);
   1064 
   1065         while (EFI_ERROR (gBS->CheckEvent (TimeOutEvt))) {
   1066           if (IsAddressOk) {
   1067             Status = EFI_SUCCESS;
   1068             break;
   1069           }
   1070         }
   1071       }
   1072 
   1073       IfCb->IfCfg->UnregisterDataNotify (
   1074                      IfCb->IfCfg,
   1075                      Ip4Config2DataTypeManualAddress,
   1076                      MappedEvt
   1077                      );
   1078 
   1079       if (EFI_ERROR (Status)) {
   1080         ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_SET_ADDR_FAILED), gShellNetwork1HiiHandle, Status);
   1081         ShellStatus = SHELL_ACCESS_DENIED;
   1082         goto ON_EXIT;
   1083       }
   1084 
   1085       //
   1086       // Set gateway.
   1087       //
   1088       DataSize = sizeof (EFI_IPv4_ADDRESS);
   1089 
   1090       Status = IfCb->IfCfg->SetData (
   1091                               IfCb->IfCfg,
   1092                               Ip4Config2DataTypeGateway,
   1093                               DataSize,
   1094                               &Gateway
   1095                               );
   1096       if (EFI_ERROR (Status)) {
   1097         ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_SET_ADDR_FAILED), gShellNetwork1HiiHandle, Status);
   1098         ShellStatus = SHELL_ACCESS_DENIED;
   1099         goto ON_EXIT;
   1100       }
   1101 
   1102       VarArg = VarArg->Next;
   1103 
   1104     } else if (StrCmp (VarArg->Arg, L"dns") == 0) {
   1105       //
   1106       // Get DNS addresses.
   1107       //
   1108       VarArg = VarArg->Next;
   1109       Tmp    = VarArg;
   1110       Index  = 0;
   1111       while (Tmp != NULL) {
   1112         Index ++;
   1113         Tmp = Tmp->Next;
   1114       }
   1115 
   1116       Dns   = AllocatePool (Index * sizeof (EFI_IPv4_ADDRESS));
   1117       if (Dns == NULL) {
   1118         ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_OUT_MEM), gShellNetwork1HiiHandle, L"ifconfig");
   1119         ShellStatus = SHELL_OUT_OF_RESOURCES;
   1120         goto ON_EXIT;
   1121       }
   1122       Tmp   = VarArg;
   1123       Index = 0;
   1124       while (Tmp != NULL) {
   1125         Status = NetLibStrToIp4 (Tmp->Arg, Dns + Index);
   1126         if (EFI_ERROR(Status)) {
   1127           ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_IFCONFIG_INVALID_IPADDRESS), gShellNetwork1HiiHandle, Tmp->Arg);
   1128           ShellStatus = SHELL_INVALID_PARAMETER;
   1129           goto ON_EXIT;
   1130         }
   1131         Index ++;
   1132         Tmp = Tmp->Next;
   1133       }
   1134 
   1135       VarArg = Tmp;
   1136 
   1137       //
   1138       // Set DNS addresses.
   1139       //
   1140       DataSize = Index * sizeof (EFI_IPv4_ADDRESS);
   1141 
   1142       Status = IfCb->IfCfg->SetData (
   1143                               IfCb->IfCfg,
   1144                               Ip4Config2DataTypeDnsServer,
   1145                               DataSize,
   1146                               Dns
   1147                               );
   1148       if (EFI_ERROR (Status)) {
   1149         ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_ERR_AD), gShellNetwork1HiiHandle, L"ifconfig");
   1150         ShellStatus = SHELL_ACCESS_DENIED;
   1151         goto ON_EXIT;
   1152       }
   1153     }
   1154   }
   1155 
   1156 ON_EXIT:
   1157   if (Dns != NULL) {
   1158     FreePool (Dns);
   1159   }
   1160 
   1161   return ShellStatus;
   1162 
   1163 }
   1164 
   1165 /**
   1166   The ifconfig command main process.
   1167 
   1168   @param[in]   Private    The pointer of IFCONFIG_PRIVATE_DATA.
   1169 
   1170   @retval SHELL_SUCCESS  ifconfig command processed successfully.
   1171   @retval others         The ifconfig command process failed.
   1172 
   1173 **/
   1174 SHELL_STATUS
   1175 IfConfig (
   1176   IN IFCONFIG_PRIVATE_DATA    *Private
   1177   )
   1178 {
   1179   EFI_STATUS    Status;
   1180   SHELL_STATUS  ShellStatus;
   1181 
   1182   ShellStatus = SHELL_SUCCESS;
   1183 
   1184   //
   1185   // Get configure information of all interfaces.
   1186   //
   1187   Status = IfConfigGetInterfaceInfo (
   1188              Private->IfName,
   1189              &Private->IfList
   1190              );
   1191   if (EFI_ERROR (Status)) {
   1192     ShellStatus = SHELL_NOT_FOUND;
   1193     goto ON_EXIT;
   1194   }
   1195 
   1196   switch (Private->OpCode) {
   1197   case IfConfigOpList:
   1198     ShellStatus = IfConfigShowInterfaceInfo (&Private->IfList);
   1199     break;
   1200 
   1201   case IfConfigOpClear:
   1202     ShellStatus = IfConfigClearInterfaceInfo (&Private->IfList, Private->IfName);
   1203     break;
   1204 
   1205   case IfConfigOpSet:
   1206     ShellStatus = IfConfigSetInterfaceInfo (&Private->IfList, Private->VarArg);
   1207     break;
   1208 
   1209   default:
   1210     ShellStatus = SHELL_UNSUPPORTED;
   1211   }
   1212 
   1213 ON_EXIT:
   1214   return ShellStatus;
   1215 }
   1216 
   1217 /**
   1218   The ifconfig command cleanup process, free the allocated memory.
   1219 
   1220   @param[in]   Private    The pointer of  IFCONFIG_PRIVATE_DATA.
   1221 
   1222 **/
   1223 VOID
   1224 IfConfigCleanup (
   1225   IN IFCONFIG_PRIVATE_DATA  *Private
   1226   )
   1227 {
   1228   LIST_ENTRY                *Entry;
   1229   LIST_ENTRY                *NextEntry;
   1230   IFCONFIG_INTERFACE_CB     *IfCb;
   1231 
   1232   ASSERT (Private != NULL);
   1233 
   1234   //
   1235   // Clean the list which save the set config Args.
   1236   //
   1237   if (Private->VarArg != NULL) {
   1238     FreeArgList (Private->VarArg);
   1239   }
   1240 
   1241   if (Private->IfName != NULL) {
   1242     FreePool (Private->IfName);
   1243   }
   1244 
   1245   //
   1246   // Clean the IFCONFIG_INTERFACE_CB list.
   1247   //
   1248   NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, &Private->IfList) {
   1249     IfCb = NET_LIST_USER_STRUCT (Entry, IFCONFIG_INTERFACE_CB, Link);
   1250 
   1251     RemoveEntryList (&IfCb->Link);
   1252 
   1253     if (IfCb->IfInfo != NULL) {
   1254 
   1255       FreePool (IfCb->IfInfo);
   1256     }
   1257 
   1258     FreePool (IfCb);
   1259   }
   1260 
   1261   FreePool (Private);
   1262 }
   1263 
   1264 /**
   1265   Function for 'ifconfig' command.
   1266 
   1267   @param[in] ImageHandle  Handle to the Image (NULL if Internal).
   1268   @param[in] SystemTable  Pointer to the System Table (NULL if Internal).
   1269 
   1270   @retval EFI_SUCCESS    ifconfig command processed successfully.
   1271   @retval others         The ifconfig command process failed.
   1272 
   1273 **/
   1274 SHELL_STATUS
   1275 EFIAPI
   1276 ShellCommandRunIfconfig (
   1277   IN EFI_HANDLE        ImageHandle,
   1278   IN EFI_SYSTEM_TABLE  *SystemTable
   1279   )
   1280 {
   1281   EFI_STATUS                Status;
   1282   IFCONFIG_PRIVATE_DATA     *Private;
   1283   LIST_ENTRY                *ParamPackage;
   1284   SHELL_STATUS              ShellStatus;
   1285   CONST CHAR16              *ValueStr;
   1286   ARG_LIST                  *ArgList;
   1287   CHAR16                    *ProblemParam;
   1288   CHAR16                    *Str;
   1289 
   1290   Status = EFI_INVALID_PARAMETER;
   1291   Private = NULL;
   1292   ShellStatus = SHELL_SUCCESS;
   1293 
   1294   Status = ShellCommandLineParseEx (mIfConfigCheckList, &ParamPackage, &ProblemParam, TRUE, FALSE);
   1295   if (EFI_ERROR (Status)) {
   1296     if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) {
   1297       ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellNetwork1HiiHandle, L"ifconfig", ProblemParam);
   1298       FreePool(ProblemParam);
   1299       ShellStatus = SHELL_INVALID_PARAMETER;
   1300     } else {
   1301       ASSERT(FALSE);
   1302     }
   1303 
   1304     goto ON_EXIT;
   1305   }
   1306 
   1307   //
   1308   // To handle unsupported option.
   1309   //
   1310   if (ShellCommandLineGetFlag (ParamPackage, L"-c")) {
   1311     ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_UNSUPPORTED_OPTION), gShellNetwork1HiiHandle,L"-c");
   1312     ShellStatus = SHELL_INVALID_PARAMETER;
   1313     goto ON_EXIT;
   1314   }
   1315 
   1316   //
   1317   // To handle no option.
   1318   //
   1319   if (!ShellCommandLineGetFlag (ParamPackage, L"-r") && !ShellCommandLineGetFlag (ParamPackage, L"-s") &&
   1320       !ShellCommandLineGetFlag (ParamPackage, L"-l")) {
   1321     ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_LACK_OPTION), gShellNetwork1HiiHandle);
   1322     ShellStatus = SHELL_INVALID_PARAMETER;
   1323     goto ON_EXIT;
   1324   }
   1325 
   1326   //
   1327   // To handle conflict options.
   1328   //
   1329   if (((ShellCommandLineGetFlag (ParamPackage, L"-r")) && (ShellCommandLineGetFlag (ParamPackage, L"-s"))) ||
   1330       ((ShellCommandLineGetFlag (ParamPackage, L"-r")) && (ShellCommandLineGetFlag (ParamPackage, L"-l"))) ||
   1331       ((ShellCommandLineGetFlag (ParamPackage, L"-s")) && (ShellCommandLineGetFlag (ParamPackage, L"-l")))) {
   1332     ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_CON), gShellNetwork1HiiHandle, L"ifconfig");
   1333     ShellStatus = SHELL_INVALID_PARAMETER;
   1334     goto ON_EXIT;
   1335   }
   1336 
   1337   Private = AllocateZeroPool (sizeof (IFCONFIG_PRIVATE_DATA));
   1338   if (Private == NULL) {
   1339     ShellStatus = SHELL_OUT_OF_RESOURCES;
   1340     goto ON_EXIT;
   1341   }
   1342 
   1343   InitializeListHead (&Private->IfList);
   1344 
   1345   //
   1346   // To get interface name for the list option.
   1347   //
   1348   if (ShellCommandLineGetFlag (ParamPackage, L"-l")) {
   1349     Private->OpCode = IfConfigOpList;
   1350     ValueStr = ShellCommandLineGetValue (ParamPackage, L"-l");
   1351     if (ValueStr != NULL) {
   1352       Str = AllocateCopyPool (StrSize (ValueStr), ValueStr);
   1353       if (Str == NULL) {
   1354         ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_OUT_MEM), gShellNetwork1HiiHandle, L"ifconfig");
   1355         ShellStatus = SHELL_OUT_OF_RESOURCES;
   1356         goto ON_EXIT;
   1357       }
   1358       Private->IfName = Str;
   1359     }
   1360   }
   1361 
   1362   //
   1363   // To get interface name for the clear option.
   1364   //
   1365   if (ShellCommandLineGetFlag (ParamPackage, L"-r")) {
   1366     Private->OpCode = IfConfigOpClear;
   1367     ValueStr = ShellCommandLineGetValue (ParamPackage, L"-r");
   1368     if (ValueStr != NULL) {
   1369       Str = AllocateCopyPool (StrSize (ValueStr), ValueStr);
   1370       if (Str == NULL) {
   1371         ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_OUT_MEM), gShellNetwork1HiiHandle, L"ifconfig");
   1372         ShellStatus = SHELL_OUT_OF_RESOURCES;
   1373         goto ON_EXIT;
   1374       }
   1375       Private->IfName = Str;
   1376     }
   1377   }
   1378 
   1379   //
   1380   // To get interface name and corresponding Args for the set option.
   1381   //
   1382   if (ShellCommandLineGetFlag (ParamPackage, L"-s")) {
   1383     ValueStr = ShellCommandLineGetValue (ParamPackage, L"-s");
   1384     if (ValueStr == NULL) {
   1385       ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_LACK_INTERFACE), gShellNetwork1HiiHandle);
   1386       ShellStatus = SHELL_INVALID_PARAMETER;
   1387       goto ON_EXIT;
   1388     }
   1389 
   1390     //
   1391     // To split the configuration into multi-section.
   1392     //
   1393     ArgList = SplitStrToList (ValueStr, L' ');
   1394     if (ArgList == NULL) {
   1395       ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_OUT_MEM), gShellNetwork1HiiHandle, L"ifconfig");
   1396       ShellStatus = SHELL_OUT_OF_RESOURCES;
   1397       goto ON_EXIT;
   1398     }
   1399 
   1400     Private->OpCode = IfConfigOpSet;
   1401     Private->IfName = ArgList->Arg;
   1402 
   1403     Private->VarArg = ArgList->Next;
   1404 
   1405     if (Private->IfName == NULL || Private->VarArg == NULL) {
   1406       ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_LACK_COMMAND), gShellNetwork1HiiHandle);
   1407       ShellStatus = SHELL_INVALID_PARAMETER;
   1408       goto ON_EXIT;
   1409     }
   1410   }
   1411 
   1412   //
   1413   // Main process of ifconfig.
   1414   //
   1415   ShellStatus = IfConfig (Private);
   1416 
   1417 ON_EXIT:
   1418 
   1419   ShellCommandLineFreeVarList (ParamPackage);
   1420 
   1421   if (Private != NULL) {
   1422     IfConfigCleanup (Private);
   1423   }
   1424 
   1425   return ShellStatus;
   1426 }
   1427