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