Home | History | Annotate | Download | only in IfConfig6
      1 /** @file
      2   The implementation for Shell application IfConfig6.
      3 
      4   Copyright (c) 2009 - 2016, Intel Corporation. All rights reserved.<BR>
      5 
      6   This program and the accompanying materials
      7   are licensed and made available under the terms and conditions of the BSD License
      8   which accompanies this distribution.  The full text of the license may be found at
      9   http://opensource.org/licenses/bsd-license.php.
     10 
     11   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     12   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     13 
     14 **/
     15 
     16 #include <Library/ShellLib.h>
     17 #include <Library/BaseMemoryLib.h>
     18 #include <Library/BaseLib.h>
     19 #include <Library/MemoryAllocationLib.h>
     20 #include <Library/DebugLib.h>
     21 #include <Library/UefiBootServicesTableLib.h>
     22 #include <Library/UefiHiiServicesLib.h>
     23 #include <Library/HiiLib.h>
     24 #include <Library/NetLib.h>
     25 
     26 #include <Protocol/Ip6.h>
     27 #include <Protocol/Ip6Config.h>
     28 
     29 #include "IfConfig6.h"
     30 
     31 //
     32 // String token ID of ifconfig6 command help message text.
     33 //
     34 GLOBAL_REMOVE_IF_UNREFERENCED EFI_STRING_ID mStringIfconfig6HelpTokenId = STRING_TOKEN (STR_IFCONFIG6_HELP);
     35 
     36 EFI_HII_HANDLE      mHiiHandle;
     37 
     38 SHELL_PARAM_ITEM    mIfConfig6CheckList[] = {
     39   {
     40     L"-b",
     41     TypeFlag
     42   },
     43   {
     44     L"-s",
     45     TypeMaxValue
     46   },
     47   {
     48     L"-l",
     49     TypeValue
     50   },
     51   {
     52     L"-r",
     53     TypeValue
     54   },
     55   {
     56     NULL,
     57     TypeMax
     58   },
     59 };
     60 
     61 VAR_CHECK_ITEM  mSetCheckList[] = {
     62   {
     63    L"auto",
     64     0x00000001,
     65     0x00000001,
     66     FlagTypeSingle
     67   },
     68   {
     69     L"man",
     70     0x00000002,
     71     0x00000001,
     72     FlagTypeSingle
     73   },
     74   {
     75     L"host",
     76     0x00000004,
     77     0x00000002,
     78     FlagTypeSingle
     79   },
     80   {
     81     L"dad",
     82     0x00000008,
     83     0x00000004,
     84     FlagTypeSingle
     85   },
     86   {
     87     L"gw",
     88     0x00000010,
     89     0x00000008,
     90     FlagTypeSingle
     91   },
     92   {
     93     L"dns",
     94     0x00000020,
     95     0x00000010,
     96     FlagTypeSingle
     97   },
     98   {
     99     L"id",
    100     0x00000040,
    101     0x00000020,
    102     FlagTypeSingle
    103   },
    104   {
    105     NULL,
    106     0x0,
    107     0x0,
    108     FlagTypeSkipUnknown
    109   },
    110 };
    111 
    112 /**
    113   Split a string with specified separator and save the substring to a list.
    114 
    115   @param[in]    String       The pointer of the input string.
    116   @param[in]    Separator    The specified separator.
    117 
    118   @return The pointer of headnode of ARG_LIST.
    119 
    120 **/
    121 ARG_LIST *
    122 SplitStrToList (
    123   IN CONST CHAR16    *String,
    124   IN CHAR16          Separator
    125   )
    126 {
    127   CHAR16      *Str;
    128   CHAR16      *ArgStr;
    129   ARG_LIST    *ArgList;
    130   ARG_LIST    *ArgNode;
    131 
    132   if (String == NULL || *String == L'\0') {
    133     return NULL;
    134   }
    135 
    136   //
    137   // Copy the CONST string to a local copy.
    138   //
    139   Str     = AllocateCopyPool (StrSize (String), String);
    140   ASSERT (Str != NULL);
    141   ArgStr  = Str;
    142 
    143   //
    144   // init a node for the list head.
    145   //
    146   ArgNode = (ARG_LIST *) AllocateZeroPool (sizeof (ARG_LIST));
    147   ASSERT (ArgNode != NULL);
    148   ArgList = ArgNode;
    149 
    150   //
    151   // Split the local copy and save in the list node.
    152   //
    153   while (*Str != L'\0') {
    154     if (*Str == Separator) {
    155       *Str          = L'\0';
    156       ArgNode->Arg  = ArgStr;
    157       ArgStr        = Str + 1;
    158       ArgNode->Next = (ARG_LIST *) AllocateZeroPool (sizeof (ARG_LIST));
    159       ASSERT (ArgNode->Next != NULL);
    160       ArgNode = ArgNode->Next;
    161     }
    162 
    163     Str++;
    164   }
    165 
    166   ArgNode->Arg  = ArgStr;
    167   ArgNode->Next = NULL;
    168 
    169   return ArgList;
    170 }
    171 
    172 /**
    173   Check the correctness of input Args with '-s' option.
    174 
    175   @param[in]    CheckList    The pointer of VAR_CHECK_ITEM array.
    176   @param[in]    Name         The pointer of input arg.
    177   @param[in]    Init         The switch to execute the check.
    178 
    179   @return The value of VAR_CHECK_CODE.
    180 
    181 **/
    182 VAR_CHECK_CODE
    183 IfConfig6RetriveCheckListByName(
    184   IN VAR_CHECK_ITEM    *CheckList,
    185   IN CHAR16            *Name,
    186   IN BOOLEAN           Init
    187 )
    188 {
    189   STATIC UINT32     CheckDuplicate;
    190   STATIC UINT32     CheckConflict;
    191   VAR_CHECK_CODE    RtCode;
    192   UINT32            Index;
    193   VAR_CHECK_ITEM    Arg;
    194 
    195   if (Init) {
    196     CheckDuplicate = 0;
    197     CheckConflict  = 0;
    198     return VarCheckOk;
    199   }
    200 
    201   RtCode  = VarCheckOk;
    202   Index   = 0;
    203   Arg     = CheckList[Index];
    204 
    205   //
    206   // Check the Duplicated/Conflicted/Unknown input Args.
    207   //
    208   while (Arg.FlagStr != NULL) {
    209     if (StrCmp (Arg.FlagStr, Name) == 0) {
    210 
    211       if (CheckDuplicate & Arg.FlagID) {
    212         RtCode = VarCheckDuplicate;
    213         break;
    214       }
    215 
    216       if (CheckConflict & Arg.ConflictMask) {
    217         RtCode = VarCheckConflict;
    218         break;
    219       }
    220 
    221       CheckDuplicate |= Arg.FlagID;
    222       CheckConflict  |= Arg.ConflictMask;
    223       break;
    224     }
    225 
    226     Arg = CheckList[++Index];
    227   }
    228 
    229   if (Arg.FlagStr == NULL) {
    230     RtCode = VarCheckUnknown;
    231   }
    232 
    233   return RtCode;
    234 }
    235 
    236 /**
    237   The notify function of create event when performing a manual config.
    238 
    239   @param[in]    Event        The event this notify function registered to.
    240   @param[in]    Context      Pointer to the context data registered to the event.
    241 
    242 **/
    243 VOID
    244 EFIAPI
    245 IfConfig6ManualAddressNotify (
    246   IN EFI_EVENT    Event,
    247   IN VOID         *Context
    248   )
    249 {
    250   *((BOOLEAN *) Context) = TRUE;
    251 }
    252 
    253 /**
    254   Print MAC address.
    255 
    256   @param[in]    Node    The pointer of MAC address buffer.
    257   @param[in]    Size    The size of MAC address buffer.
    258 
    259 **/
    260 VOID
    261 IfConfig6PrintMacAddr (
    262   IN UINT8     *Node,
    263   IN UINT32    Size
    264   )
    265 {
    266   UINTN    Index;
    267 
    268   ASSERT (Size <= MACADDRMAXSIZE);
    269 
    270   for (Index = 0; Index < Size; Index++) {
    271     ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_INFO_MAC_ADDR_BODY), mHiiHandle, Node[Index]);
    272     if (Index + 1 < Size) {
    273       ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_INFO_COLON), mHiiHandle);
    274     }
    275   }
    276 
    277   ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_INFO_NEWLINE), mHiiHandle);
    278 }
    279 
    280 /**
    281   Print IPv6 address.
    282 
    283   @param[in]    Ip           The pointer of Ip bufffer in EFI_IPv6_ADDRESS format.
    284   @param[in]    PrefixLen    The pointer of PrefixLen that describes the size Prefix.
    285 
    286 **/
    287 VOID
    288 IfConfig6PrintIpAddr (
    289   IN EFI_IPv6_ADDRESS    *Ip,
    290   IN UINT8               *PrefixLen
    291   )
    292 {
    293   UINTN      Index;
    294   BOOLEAN    Short;
    295 
    296   Short = FALSE;
    297 
    298   for (Index = 0; Index < PREFIXMAXLEN; Index = Index + 2) {
    299 
    300     if (!Short && (Index + 1 < PREFIXMAXLEN) && (Index % 2 == 0) && (Ip->Addr[Index] == 0) && (Ip->Addr[Index + 1] == 0)) {
    301       //
    302       // Deal with the case of ::.
    303       //
    304       if (Index == 0) {
    305         //
    306         // :: is at the beginning of the address.
    307         //
    308         ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_INFO_COLON), mHiiHandle);
    309       }
    310       ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_INFO_COLON), mHiiHandle);
    311 
    312       while ((Ip->Addr[Index] == 0) && (Ip->Addr[Index + 1] == 0) && (Index < PREFIXMAXLEN)) {
    313         Index = Index + 2;
    314         if (Index > PREFIXMAXLEN - 2) {
    315           break;
    316         }
    317       }
    318 
    319       Short = TRUE;
    320 
    321       if (Index == PREFIXMAXLEN) {
    322         //
    323         // :: is at the end of the address.
    324         //
    325         break;
    326       }
    327     }
    328 
    329     if (Index < PREFIXMAXLEN - 1) {
    330       ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_INFO_IP_ADDR_BODY), mHiiHandle, Ip->Addr[Index]);
    331       ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_INFO_IP_ADDR_BODY), mHiiHandle, Ip->Addr[Index + 1]);
    332     }
    333 
    334     if (Index + 2 < PREFIXMAXLEN) {
    335       ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_INFO_COLON), mHiiHandle);
    336     }
    337   }
    338 
    339   if (PrefixLen != NULL) {
    340     ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_INFO_PREFIX_LEN), mHiiHandle, *PrefixLen);
    341   }
    342 }
    343 
    344 /**
    345   Pick up host IPv6 address in string format from Args with "-s" option and convert it to EFI_IP6_CONFIG_MANUAL_ADDRESS format.
    346 
    347   @param[in, out]    Arg        The pointer of the address of ARG_LIST which save Args with the "-s" option.
    348   @param[out]        Buf        The pointer of the address of EFI_IP6_CONFIG_MANUAL_ADDRESS.
    349   @param[out]        BufSize    The pointer of BufSize that describes the size of Buf in bytes.
    350 
    351   @retval EFI_SUCCESS    The convertion is successful.
    352   @retval Others         Does't find the host address, or it is an invalid IPv6 address in string format.
    353 
    354 **/
    355 EFI_STATUS
    356 IfConfig6ParseManualAddressList (
    357   IN OUT ARG_LIST                         **Arg,
    358      OUT EFI_IP6_CONFIG_MANUAL_ADDRESS    **Buf,
    359      OUT UINTN                            *BufSize
    360   )
    361 {
    362   EFI_STATUS                       Status;
    363   EFI_IP6_CONFIG_MANUAL_ADDRESS    *AddrBuf;
    364   ARG_LIST                         *VarArg;
    365   EFI_IPv6_ADDRESS                 Address;
    366   UINT8                            Prefix;
    367   UINT8                            AddrCnt;
    368 
    369   Prefix   = 0;
    370   AddrCnt  = 0;
    371   *BufSize = 0;
    372   *Buf     = NULL;
    373   VarArg   = *Arg;
    374   Status   = EFI_SUCCESS;
    375 
    376   //
    377   // Go through the list to check the correctness of input host ip6 address.
    378   //
    379   while ((!EFI_ERROR (Status)) && (VarArg != NULL)) {
    380 
    381     Status = NetLibStrToIp6andPrefix (VarArg->Arg, &Address, &Prefix);
    382 
    383     if (EFI_ERROR (Status)) {
    384       //
    385       // host ip ip ... gw
    386       //
    387       break;
    388     }
    389 
    390     VarArg = VarArg->Next;
    391     AddrCnt++;
    392   }
    393 
    394   if (AddrCnt == 0) {
    395     return EFI_INVALID_PARAMETER;
    396   }
    397 
    398   AddrBuf = AllocateZeroPool (AddrCnt * sizeof (EFI_IP6_CONFIG_MANUAL_ADDRESS));
    399   ASSERT (AddrBuf != NULL);
    400 
    401   AddrCnt = 0;
    402   VarArg  = *Arg;
    403   Status  = EFI_SUCCESS;
    404 
    405   //
    406   // Go through the list to fill in the EFI_IP6_CONFIG_MANUAL_ADDRESS structure.
    407   //
    408   while ((!EFI_ERROR (Status)) && (VarArg != NULL)) {
    409 
    410     Status = NetLibStrToIp6andPrefix (VarArg->Arg, &Address, &Prefix);
    411 
    412     if (EFI_ERROR (Status)) {
    413       break;
    414     }
    415 
    416     //
    417     // If prefix length is not set, set it as Zero here. In the IfConfigSetInterfaceInfo()
    418     // Zero prefix, length will be transfered to default prefix length.
    419     //
    420     if (Prefix == 0xFF) {
    421       Prefix = 0;
    422     }
    423     AddrBuf[AddrCnt].IsAnycast    = FALSE;
    424     AddrBuf[AddrCnt].PrefixLength = Prefix;
    425     IP6_COPY_ADDRESS (&AddrBuf[AddrCnt].Address, &Address);
    426     VarArg = VarArg->Next;
    427     AddrCnt++;
    428   }
    429 
    430   *Arg = VarArg;
    431 
    432   if (EFI_ERROR (Status) && (Status != EFI_INVALID_PARAMETER)) {
    433     goto ON_ERROR;
    434   }
    435 
    436   *Buf     = AddrBuf;
    437   *BufSize = AddrCnt * sizeof (EFI_IP6_CONFIG_MANUAL_ADDRESS);
    438 
    439   return EFI_SUCCESS;
    440 
    441 ON_ERROR:
    442 
    443   FreePool (AddrBuf);
    444   return Status;
    445 }
    446 
    447 /**
    448   Pick up gw/dns IPv6 address in string format from Args with "-s" option and convert it to EFI_IPv6_ADDRESS format.
    449 
    450   @param[in, out]    Arg        The pointer of the address of ARG_LIST that save Args with the "-s" option.
    451   @param[out]        Buf        The pointer of the address of EFI_IPv6_ADDRESS.
    452   @param[out]        BufSize    The pointer of BufSize that describes the size of Buf in bytes.
    453 
    454   @retval EFI_SUCCESS    The conversion is successful.
    455   @retval Others         Doesn't find the host address, or it is an invalid IPv6 address in string format.
    456 
    457 **/
    458 EFI_STATUS
    459 IfConfig6ParseGwDnsAddressList (
    460   IN OUT ARG_LIST            **Arg,
    461      OUT EFI_IPv6_ADDRESS    **Buf,
    462      OUT UINTN               *BufSize
    463   )
    464 {
    465   EFI_STATUS          Status;
    466   EFI_IPv6_ADDRESS    *AddrBuf;
    467   ARG_LIST            *VarArg;
    468   EFI_IPv6_ADDRESS    Address;
    469   UINT8               Prefix;
    470   UINT8               AddrCnt;
    471 
    472   AddrCnt  = 0;
    473   *BufSize = 0;
    474   *Buf     = NULL;
    475   VarArg   = *Arg;
    476   Status   = EFI_SUCCESS;
    477 
    478   //
    479   // Go through the list to check the correctness of input gw/dns address.
    480   //
    481   while ((!EFI_ERROR (Status)) && (VarArg != NULL)) {
    482 
    483     Status = NetLibStrToIp6andPrefix (VarArg->Arg, &Address, &Prefix);
    484 
    485     if (EFI_ERROR (Status)) {
    486       //
    487       // gw ip ip ... host
    488       //
    489       break;
    490     }
    491 
    492     VarArg = VarArg->Next;
    493     AddrCnt++;
    494   }
    495 
    496   if (AddrCnt == 0) {
    497     return EFI_INVALID_PARAMETER;
    498   }
    499 
    500   AddrBuf = AllocateZeroPool (AddrCnt * sizeof (EFI_IPv6_ADDRESS));
    501   ASSERT (AddrBuf != NULL);
    502 
    503   AddrCnt = 0;
    504   VarArg  = *Arg;
    505   Status  = EFI_SUCCESS;
    506 
    507   //
    508   // Go through the list to fill in the EFI_IPv6_ADDRESS structure.
    509   //
    510   while ((!EFI_ERROR (Status)) && (VarArg != NULL)) {
    511 
    512     Status = NetLibStrToIp6andPrefix (VarArg->Arg, &Address, &Prefix);
    513 
    514     if (EFI_ERROR (Status)) {
    515       break;
    516     }
    517 
    518     IP6_COPY_ADDRESS (&AddrBuf[AddrCnt], &Address);
    519 
    520     VarArg = VarArg->Next;
    521     AddrCnt++;
    522   }
    523 
    524   *Arg = VarArg;
    525 
    526   if (EFI_ERROR (Status) && (Status != EFI_INVALID_PARAMETER)) {
    527    goto ON_ERROR;
    528   }
    529 
    530   *Buf     = AddrBuf;
    531   *BufSize = AddrCnt * sizeof (EFI_IPv6_ADDRESS);
    532 
    533   return EFI_SUCCESS;
    534 
    535 ON_ERROR:
    536 
    537   FreePool (AddrBuf);
    538   return Status;
    539 }
    540 
    541 /**
    542   Parse InterfaceId in string format from Args with the "-s" option and convert it to EFI_IP6_CONFIG_INTERFACE_ID format.
    543 
    544   @param[in, out]   Arg     The pointer of the address of ARG_LIST that saves Args with the "-s" option.
    545   @param[out]       IfId    The pointer of EFI_IP6_CONFIG_INTERFACE_ID.
    546 
    547   @retval EFI_SUCCESS              The get status processed successfullly.
    548   @retval EFI_INVALID_PARAMETER    The get status process failed.
    549 
    550 **/
    551 EFI_STATUS
    552 IfConfig6ParseInterfaceId (
    553   IN OUT ARG_LIST                       **Arg,
    554      OUT EFI_IP6_CONFIG_INTERFACE_ID    **IfId
    555   )
    556 {
    557   UINT8     Index;
    558   UINT8     NodeVal;
    559   CHAR16    *IdStr;
    560 
    561   if (*Arg == NULL) {
    562     return EFI_INVALID_PARAMETER;
    563   }
    564 
    565   Index = 0;
    566   IdStr = (*Arg)->Arg;
    567   ASSERT (IfId != NULL);
    568   *IfId = AllocateZeroPool (sizeof (EFI_IP6_CONFIG_INTERFACE_ID));
    569   ASSERT (*IfId != NULL);
    570 
    571   while ((*IdStr != L'\0') && (Index < 8)) {
    572 
    573     NodeVal = 0;
    574     while ((*IdStr != L':') && (*IdStr != L'\0')) {
    575 
    576       if ((*IdStr <= L'F') && (*IdStr >= L'A')) {
    577         NodeVal = (UINT8)((NodeVal << 4) + *IdStr - L'A' + 10);
    578       } else if ((*IdStr <= L'f') && (*IdStr >= L'a')) {
    579         NodeVal = (UINT8)((NodeVal << 4) + *IdStr - L'a' + 10);
    580       } else if ((*IdStr <= L'9') && (*IdStr >= L'0')) {
    581         NodeVal = (UINT8)((NodeVal << 4) + *IdStr - L'0');
    582       } else {
    583         FreePool (*IfId);
    584         return EFI_INVALID_PARAMETER;
    585       }
    586 
    587       IdStr++;
    588     }
    589 
    590     (*IfId)->Id[Index++] = NodeVal;
    591 
    592     if (*IdStr == L':') {
    593       IdStr++;
    594     }
    595   }
    596 
    597   *Arg = (*Arg)->Next;
    598   return EFI_SUCCESS;
    599 }
    600 
    601 /**
    602   Parse dad in string format from Args with the "-s" option and convert it to UINT32 format.
    603 
    604   @param[in, out]   Arg      The pointer of the address of ARG_LIST that saves Args with the "-s" option.
    605   @param[out]       Xmits    The pointer of Xmits.
    606 
    607   @retval EFI_SUCCESS    The get status processed successfully.
    608   @retval others         The get status process failed.
    609 
    610 **/
    611 EFI_STATUS
    612 IfConfig6ParseDadXmits (
    613   IN OUT ARG_LIST    **Arg,
    614      OUT UINT32      *Xmits
    615   )
    616 {
    617   CHAR16    *ValStr;
    618 
    619   if (*Arg == NULL) {
    620     return EFI_INVALID_PARAMETER;
    621   }
    622 
    623   ValStr = (*Arg)->Arg;
    624   *Xmits = 0;
    625 
    626   while (*ValStr != L'\0') {
    627 
    628     if ((*ValStr <= L'9') && (*ValStr >= L'0')) {
    629 
    630       *Xmits = (*Xmits * 10) + (*ValStr - L'0');
    631 
    632     } else {
    633 
    634       return EFI_INVALID_PARAMETER;
    635     }
    636 
    637     ValStr++;
    638   }
    639 
    640   *Arg = (*Arg)->Next;
    641   return EFI_SUCCESS;
    642 }
    643 
    644 /**
    645   The get current status of all handles.
    646 
    647   @param[in]   ImageHandle    The handle of  ImageHandle.
    648   @param[in]   IfName         The pointer of  IfName(interface name).
    649   @param[in]   IfList         The pointer of  IfList(interface list).
    650 
    651   @retval EFI_SUCCESS    The get status processed successfully.
    652   @retval others         The get status process failed.
    653 
    654 **/
    655 EFI_STATUS
    656 IfConfig6GetInterfaceInfo (
    657   IN EFI_HANDLE    ImageHandle,
    658   IN CHAR16        *IfName,
    659   IN LIST_ENTRY    *IfList
    660   )
    661 {
    662   EFI_STATUS                       Status;
    663   UINTN                            HandleIndex;
    664   UINTN                            HandleNum;
    665   EFI_HANDLE                       *HandleBuffer;
    666   EFI_IP6_CONFIG_PROTOCOL          *Ip6Cfg;
    667   EFI_IP6_CONFIG_INTERFACE_INFO    *IfInfo;
    668   IFCONFIG6_INTERFACE_CB           *IfCb;
    669   UINTN                            DataSize;
    670 
    671   HandleBuffer = NULL;
    672   HandleNum    = 0;
    673 
    674   IfInfo       = NULL;
    675   IfCb         = NULL;
    676 
    677   //
    678   // Locate all the handles with ip6 service binding protocol.
    679   //
    680   Status = gBS->LocateHandleBuffer (
    681                   ByProtocol,
    682                   &gEfiIp6ServiceBindingProtocolGuid,
    683                   NULL,
    684                   &HandleNum,
    685                   &HandleBuffer
    686                  );
    687   if (EFI_ERROR (Status) || (HandleNum == 0)) {
    688     return EFI_ABORTED;
    689   }
    690 
    691   //
    692   // Enumerate all handles that installed with ip6 service binding protocol.
    693   //
    694   for (HandleIndex = 0; HandleIndex < HandleNum; HandleIndex++) {
    695     IfCb      = NULL;
    696     IfInfo    = NULL;
    697     DataSize  = 0;
    698 
    699     //
    700     // Ip6config protocol and ip6 service binding protocol are installed
    701     // on the same handle.
    702     //
    703     ASSERT (HandleBuffer != NULL);
    704     Status = gBS->HandleProtocol (
    705                     HandleBuffer[HandleIndex],
    706                     &gEfiIp6ConfigProtocolGuid,
    707                     (VOID **) &Ip6Cfg
    708                     );
    709 
    710     if (EFI_ERROR (Status)) {
    711       goto ON_ERROR;
    712     }
    713     //
    714     // Get the interface information size.
    715     //
    716     Status = Ip6Cfg->GetData (
    717                        Ip6Cfg,
    718                        Ip6ConfigDataTypeInterfaceInfo,
    719                        &DataSize,
    720                        NULL
    721                        );
    722 
    723     if (Status != EFI_BUFFER_TOO_SMALL) {
    724       ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_ERR_IP6CFG_GETDATA), mHiiHandle, Status);
    725       goto ON_ERROR;
    726     }
    727 
    728     IfInfo = AllocateZeroPool (DataSize);
    729 
    730     if (IfInfo == NULL) {
    731       Status = EFI_OUT_OF_RESOURCES;
    732       goto ON_ERROR;
    733     }
    734     //
    735     // Get the interface info.
    736     //
    737     Status = Ip6Cfg->GetData (
    738                        Ip6Cfg,
    739                        Ip6ConfigDataTypeInterfaceInfo,
    740                        &DataSize,
    741                        IfInfo
    742                        );
    743 
    744     if (EFI_ERROR (Status)) {
    745       ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_ERR_IP6CFG_GETDATA), mHiiHandle, Status);
    746       goto ON_ERROR;
    747     }
    748     //
    749     // Check the interface name if required.
    750     //
    751     if ((IfName != NULL) && (StrCmp (IfName, IfInfo->Name) != 0)) {
    752       FreePool (IfInfo);
    753       continue;
    754     }
    755 
    756     DataSize = 0;
    757     //
    758     // Get the size of dns server list.
    759     //
    760     Status = Ip6Cfg->GetData (
    761                        Ip6Cfg,
    762                        Ip6ConfigDataTypeDnsServer,
    763                        &DataSize,
    764                        NULL
    765                        );
    766 
    767     if ((Status != EFI_BUFFER_TOO_SMALL) && (Status != EFI_NOT_FOUND)) {
    768       ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_ERR_IP6CFG_GETDATA), mHiiHandle, Status);
    769       goto ON_ERROR;
    770     }
    771 
    772     IfCb = AllocateZeroPool (sizeof (IFCONFIG6_INTERFACE_CB) + DataSize);
    773 
    774     if (IfCb == NULL) {
    775       Status = EFI_OUT_OF_RESOURCES;
    776       goto ON_ERROR;
    777     }
    778 
    779     IfCb->NicHandle = HandleBuffer[HandleIndex];
    780     IfCb->IfInfo    = IfInfo;
    781     IfCb->IfCfg     = Ip6Cfg;
    782     IfCb->DnsCnt    = (UINT32) (DataSize / sizeof (EFI_IPv6_ADDRESS));
    783 
    784     //
    785     // Get the dns server list if has.
    786     //
    787     if (DataSize > 0) {
    788 
    789       Status = Ip6Cfg->GetData (
    790                          Ip6Cfg,
    791                          Ip6ConfigDataTypeDnsServer,
    792                          &DataSize,
    793                          IfCb->DnsAddr
    794                          );
    795 
    796       if (EFI_ERROR (Status)) {
    797         ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_ERR_IP6CFG_GETDATA), mHiiHandle, Status);
    798         goto ON_ERROR;
    799       }
    800     }
    801     //
    802     // Get the interface id if has.
    803     //
    804     DataSize   = sizeof (EFI_IP6_CONFIG_INTERFACE_ID);
    805     IfCb->IfId = AllocateZeroPool (DataSize);
    806 
    807     if (IfCb->IfId == NULL) {
    808       goto ON_ERROR;
    809     }
    810 
    811     Status = Ip6Cfg->GetData (
    812                        Ip6Cfg,
    813                        Ip6ConfigDataTypeAltInterfaceId,
    814                        &DataSize,
    815                        IfCb->IfId
    816                        );
    817 
    818     if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) {
    819       ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_ERR_IP6CFG_GETDATA), mHiiHandle, Status);
    820       goto ON_ERROR;
    821     }
    822 
    823     if (Status == EFI_NOT_FOUND) {
    824       FreePool (IfCb->IfId);
    825       IfCb->IfId = NULL;
    826     }
    827     //
    828     // Get the config policy.
    829     //
    830     DataSize = sizeof (EFI_IP6_CONFIG_POLICY);
    831     Status   = Ip6Cfg->GetData (
    832                          Ip6Cfg,
    833                          Ip6ConfigDataTypePolicy,
    834                          &DataSize,
    835                          &IfCb->Policy
    836                          );
    837 
    838     if (EFI_ERROR (Status)) {
    839       ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_ERR_IP6CFG_GETDATA), mHiiHandle, Status);
    840       goto ON_ERROR;
    841     }
    842     //
    843     // Get the dad transmits.
    844     //
    845     DataSize = sizeof (EFI_IP6_CONFIG_DUP_ADDR_DETECT_TRANSMITS);
    846     Status   = Ip6Cfg->GetData (
    847                          Ip6Cfg,
    848                          Ip6ConfigDataTypeDupAddrDetectTransmits,
    849                          &DataSize,
    850                          &IfCb->Xmits
    851                          );
    852 
    853     if (EFI_ERROR (Status)) {
    854       ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_ERR_IP6CFG_GETDATA), mHiiHandle, Status);
    855       goto ON_ERROR;
    856     }
    857 
    858     InsertTailList (IfList, &IfCb->Link);
    859 
    860     if ((IfName != NULL) && (StrCmp (IfName, IfInfo->Name) == 0)) {
    861       //
    862       // Only need the appointed interface, keep the allocated buffer.
    863       //
    864       IfCb   = NULL;
    865       IfInfo = NULL;
    866       break;
    867     }
    868   }
    869 
    870   if (HandleBuffer != NULL) {
    871     FreePool (HandleBuffer);
    872   }
    873 
    874   return EFI_SUCCESS;
    875 
    876 ON_ERROR:
    877 
    878   if (IfInfo != NULL) {
    879     FreePool (IfInfo);
    880   }
    881 
    882   if (IfCb != NULL) {
    883     if (IfCb->IfId != NULL) {
    884       FreePool (IfCb->IfId);
    885     }
    886 
    887     FreePool (IfCb);
    888   }
    889 
    890   return Status;
    891 }
    892 
    893 /**
    894   The list process of the IfConfig6 application.
    895 
    896   @param[in]   IfList    The pointer of IfList(interface list).
    897 
    898   @retval EFI_SUCCESS    The IfConfig6 list processed successfully.
    899   @retval others         The IfConfig6 list process failed.
    900 
    901 **/
    902 EFI_STATUS
    903 IfConfig6ShowInterfaceInfo (
    904   IN LIST_ENTRY    *IfList
    905   )
    906 {
    907   EFI_STATUS                Status;
    908   LIST_ENTRY                *Entry;
    909   IFCONFIG6_INTERFACE_CB    *IfCb;
    910   UINTN                     Index;
    911 
    912   Entry  = IfList->ForwardLink;
    913   Status = EFI_SUCCESS;
    914 
    915   if (IsListEmpty (IfList)) {
    916     ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_ERR_INVALID_INTERFACE), mHiiHandle);
    917   }
    918 
    919   //
    920   // Go through the interface list.
    921   //
    922   while (Entry != IfList) {
    923 
    924     IfCb = BASE_CR (Entry, IFCONFIG6_INTERFACE_CB, Link);
    925 
    926     ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_INFO_BREAK), mHiiHandle);
    927 
    928     //
    929     // Print interface name.
    930     //
    931     ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_INFO_IF_NAME), mHiiHandle, IfCb->IfInfo->Name);
    932 
    933     //
    934     // Print interface config policy.
    935     //
    936     if (IfCb->Policy == Ip6ConfigPolicyAutomatic) {
    937       ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_INFO_POLICY_AUTO), mHiiHandle);
    938     } else {
    939       ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_INFO_POLICY_MAN), mHiiHandle);
    940     }
    941 
    942     //
    943     // Print dad transmit.
    944     //
    945     ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_INFO_DAD_TRANSMITS), mHiiHandle, IfCb->Xmits);
    946 
    947     //
    948     // Print interface id if has.
    949     //
    950     if (IfCb->IfId != NULL) {
    951       ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_INFO_INTERFACE_ID_HEAD), mHiiHandle);
    952 
    953       IfConfig6PrintMacAddr (
    954         IfCb->IfId->Id,
    955         8
    956         );
    957     }
    958     //
    959     // Print mac address of the interface.
    960     //
    961     ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_INFO_MAC_ADDR_HEAD), mHiiHandle);
    962 
    963     IfConfig6PrintMacAddr (
    964       IfCb->IfInfo->HwAddress.Addr,
    965       IfCb->IfInfo->HwAddressSize
    966       );
    967 
    968     //
    969     // Print ip addresses list of the interface.
    970     //
    971     ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_INFO_IP_ADDR_HEAD), mHiiHandle);
    972 
    973     for (Index = 0; Index < IfCb->IfInfo->AddressInfoCount; Index++) {
    974       IfConfig6PrintIpAddr (
    975         &IfCb->IfInfo->AddressInfo[Index].Address,
    976         &IfCb->IfInfo->AddressInfo[Index].PrefixLength
    977         );
    978       ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_INFO_NEWLINE), mHiiHandle);
    979     }
    980 
    981     //
    982     // Print dns server addresses list of the interface if has.
    983     //
    984     ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_INFO_DNS_ADDR_HEAD), mHiiHandle);
    985 
    986     for (Index = 0; Index < IfCb->DnsCnt; Index++) {
    987       IfConfig6PrintIpAddr (
    988         &IfCb->DnsAddr[Index],
    989         NULL
    990         );
    991       ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_INFO_NEWLINE), mHiiHandle);
    992     }
    993 
    994     //
    995     // Print route table of the interface if has.
    996     //
    997     ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_INFO_ROUTE_HEAD), mHiiHandle);
    998 
    999     for (Index = 0; Index < IfCb->IfInfo->RouteCount; Index++) {
   1000       IfConfig6PrintIpAddr (
   1001         &IfCb->IfInfo->RouteTable[Index].Destination,
   1002         &IfCb->IfInfo->RouteTable[Index].PrefixLength
   1003         );
   1004       ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_INFO_JOINT), mHiiHandle);
   1005 
   1006       IfConfig6PrintIpAddr (
   1007         &IfCb->IfInfo->RouteTable[Index].Gateway,
   1008         NULL
   1009         );
   1010       ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_INFO_NEWLINE), mHiiHandle);
   1011     }
   1012 
   1013     Entry = Entry->ForwardLink;
   1014   }
   1015 
   1016   ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_INFO_BREAK), mHiiHandle);
   1017 
   1018   return Status;
   1019 }
   1020 
   1021 /**
   1022   The clean process of the IfConfig6 application.
   1023 
   1024   @param[in]   IfList    The pointer of IfList(interface list).
   1025 
   1026   @retval EFI_SUCCESS    The IfConfig6 clean processed successfully.
   1027   @retval others         The IfConfig6 clean process failed.
   1028 
   1029 **/
   1030 EFI_STATUS
   1031 IfConfig6ClearInterfaceInfo (
   1032   IN LIST_ENTRY    *IfList
   1033   )
   1034 {
   1035   EFI_STATUS                Status;
   1036   LIST_ENTRY                *Entry;
   1037   IFCONFIG6_INTERFACE_CB    *IfCb;
   1038   EFI_IP6_CONFIG_POLICY     Policy;
   1039 
   1040   Policy = Ip6ConfigPolicyAutomatic;
   1041   Entry  = IfList->ForwardLink;
   1042   Status = EFI_SUCCESS;
   1043 
   1044   if (IsListEmpty (IfList)) {
   1045     ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_ERR_INVALID_INTERFACE), mHiiHandle);
   1046   }
   1047 
   1048   //
   1049   // Go through the interface list.
   1050   //
   1051   while (Entry != IfList) {
   1052 
   1053     IfCb = BASE_CR (Entry, IFCONFIG6_INTERFACE_CB, Link);
   1054 
   1055     Status = IfCb->IfCfg->SetData (
   1056                             IfCb->IfCfg,
   1057                             Ip6ConfigDataTypePolicy,
   1058                             sizeof (EFI_IP6_CONFIG_POLICY),
   1059                             &Policy
   1060                             );
   1061 
   1062     if (EFI_ERROR (Status)) {
   1063       break;
   1064     }
   1065 
   1066     Entry  = Entry->ForwardLink;
   1067   }
   1068 
   1069   return Status;
   1070 }
   1071 
   1072 /**
   1073   The set process of the IfConfig6 application.
   1074 
   1075   @param[in]   IfList    The pointer of IfList(interface list).
   1076   @param[in]   VarArg    The pointer of ARG_LIST(Args with "-s" option).
   1077 
   1078   @retval EFI_SUCCESS    The IfConfig6 set processed successfully.
   1079   @retval others         The IfConfig6 set process failed.
   1080 
   1081 **/
   1082 EFI_STATUS
   1083 IfConfig6SetInterfaceInfo (
   1084   IN LIST_ENTRY    *IfList,
   1085   IN ARG_LIST      *VarArg
   1086   )
   1087 {
   1088   EFI_STATUS                       Status;
   1089   IFCONFIG6_INTERFACE_CB           *IfCb;
   1090   EFI_IP6_CONFIG_MANUAL_ADDRESS    *CfgManAddr;
   1091   EFI_IPv6_ADDRESS                 *CfgAddr;
   1092   UINTN                            AddrSize;
   1093   EFI_IP6_CONFIG_INTERFACE_ID      *InterfaceId;
   1094   UINT32                           DadXmits;
   1095   UINT32                           CurDadXmits;
   1096   UINTN                            CurDadXmitsLen;
   1097   EFI_IP6_CONFIG_POLICY            Policy;
   1098 
   1099   VAR_CHECK_CODE                   CheckCode;
   1100   EFI_EVENT                        TimeOutEvt;
   1101   EFI_EVENT                        MappedEvt;
   1102   BOOLEAN                          IsAddressOk;
   1103 
   1104   UINTN                            DataSize;
   1105   UINT32                           Index;
   1106   UINT32                           Index2;
   1107   BOOLEAN                          IsAddressSet;
   1108   EFI_IP6_CONFIG_INTERFACE_INFO    *IfInfo;
   1109 
   1110   CfgManAddr  = NULL;
   1111   CfgAddr     = NULL;
   1112   TimeOutEvt  = NULL;
   1113   MappedEvt   = NULL;
   1114   IfInfo      = NULL;
   1115   InterfaceId = NULL;
   1116   CurDadXmits = 0;
   1117 
   1118   if (IsListEmpty (IfList)) {
   1119     ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_ERR_INVALID_INTERFACE), mHiiHandle);
   1120     return EFI_INVALID_PARAMETER;
   1121   }
   1122   //
   1123   // Make sure to set only one interface each time.
   1124   //
   1125   IfCb   = BASE_CR (IfList->ForwardLink, IFCONFIG6_INTERFACE_CB, Link);
   1126   Status = EFI_SUCCESS;
   1127 
   1128   //
   1129   // Initialize check list mechanism.
   1130   //
   1131   CheckCode = IfConfig6RetriveCheckListByName(
   1132                 NULL,
   1133                 NULL,
   1134                 TRUE
   1135                 );
   1136 
   1137   //
   1138   // Create events & timers for asynchronous settings.
   1139   //
   1140   Status = gBS->CreateEvent (
   1141                   EVT_TIMER,
   1142                   TPL_CALLBACK,
   1143                   NULL,
   1144                   NULL,
   1145                   &TimeOutEvt
   1146                   );
   1147   if (EFI_ERROR (Status)) {
   1148     goto ON_EXIT;
   1149   }
   1150 
   1151   Status = gBS->CreateEvent (
   1152                   EVT_NOTIFY_SIGNAL,
   1153                   TPL_NOTIFY,
   1154                   IfConfig6ManualAddressNotify,
   1155                   &IsAddressOk,
   1156                   &MappedEvt
   1157                   );
   1158   if (EFI_ERROR (Status)) {
   1159     goto ON_EXIT;
   1160   }
   1161   //
   1162   // Parse the setting variables.
   1163   //
   1164   while (VarArg != NULL) {
   1165      //
   1166      // Check invalid parameters (duplication & unknown & conflict).
   1167      //
   1168     CheckCode = IfConfig6RetriveCheckListByName(
   1169                   mSetCheckList,
   1170                   VarArg->Arg,
   1171                   FALSE
   1172                   );
   1173 
   1174     if (VarCheckOk != CheckCode) {
   1175       switch (CheckCode) {
   1176         case VarCheckDuplicate:
   1177           ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_ERR_DUPLICATE_COMMAND), mHiiHandle, VarArg->Arg);
   1178           break;
   1179 
   1180         case VarCheckConflict:
   1181           ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_ERR_CONFLICT_COMMAND), mHiiHandle, VarArg->Arg);
   1182           break;
   1183 
   1184         case VarCheckUnknown:
   1185           ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_ERR_UNKNOWN_COMMAND), mHiiHandle, VarArg->Arg);
   1186           break;
   1187 
   1188         default:
   1189           break;
   1190       }
   1191 
   1192       VarArg = VarArg->Next;
   1193       continue;
   1194     }
   1195     //
   1196     // Process valid variables.
   1197     //
   1198     if (StrCmp(VarArg->Arg, L"auto") == 0) {
   1199       //
   1200       // Set automaic config policy
   1201       //
   1202       Policy = Ip6ConfigPolicyAutomatic;
   1203       Status = IfCb->IfCfg->SetData (
   1204                               IfCb->IfCfg,
   1205                               Ip6ConfigDataTypePolicy,
   1206                               sizeof (EFI_IP6_CONFIG_POLICY),
   1207                               &Policy
   1208                               );
   1209 
   1210       if (EFI_ERROR(Status)) {
   1211         goto ON_EXIT;
   1212       }
   1213 
   1214       VarArg= VarArg->Next;
   1215 
   1216     } else if (StrCmp (VarArg->Arg, L"man") == 0) {
   1217       //
   1218       // Set manual config policy.
   1219       //
   1220       Policy = Ip6ConfigPolicyManual;
   1221       Status = IfCb->IfCfg->SetData (
   1222                               IfCb->IfCfg,
   1223                               Ip6ConfigDataTypePolicy,
   1224                               sizeof (EFI_IP6_CONFIG_POLICY),
   1225                               &Policy
   1226                               );
   1227 
   1228       if (EFI_ERROR(Status)) {
   1229         goto ON_EXIT;
   1230       }
   1231 
   1232       VarArg= VarArg->Next;
   1233 
   1234     } else if (StrCmp (VarArg->Arg, L"host") == 0) {
   1235       //
   1236       // Parse till the next tag or the end of command line.
   1237       //
   1238       VarArg = VarArg->Next;
   1239       Status = IfConfig6ParseManualAddressList (
   1240                  &VarArg,
   1241                  &CfgManAddr,
   1242                  &AddrSize
   1243                  );
   1244 
   1245       if (EFI_ERROR (Status)) {
   1246         if (Status == EFI_INVALID_PARAMETER) {
   1247           ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_ERR_LACK_ARGUMENTS), mHiiHandle, L"host");
   1248           continue;
   1249         } else {
   1250           goto ON_EXIT;
   1251         }
   1252       }
   1253       //
   1254       // Set static host ip6 address list.
   1255       //   This is a asynchronous process.
   1256       //
   1257       IsAddressOk = FALSE;
   1258 
   1259       Status = IfCb->IfCfg->RegisterDataNotify (
   1260                               IfCb->IfCfg,
   1261                               Ip6ConfigDataTypeManualAddress,
   1262                               MappedEvt
   1263                               );
   1264       if (EFI_ERROR (Status)) {
   1265         goto ON_EXIT;
   1266       }
   1267 
   1268       Status = IfCb->IfCfg->SetData (
   1269                               IfCb->IfCfg,
   1270                               Ip6ConfigDataTypeManualAddress,
   1271                               AddrSize,
   1272                               CfgManAddr
   1273                               );
   1274 
   1275       if (Status == EFI_NOT_READY) {
   1276         //
   1277         // Get current dad transmits count.
   1278         //
   1279         CurDadXmitsLen = sizeof (EFI_IP6_CONFIG_DUP_ADDR_DETECT_TRANSMITS);
   1280         IfCb->IfCfg->GetData (
   1281                        IfCb->IfCfg,
   1282                        Ip6ConfigDataTypeDupAddrDetectTransmits,
   1283                        &CurDadXmitsLen,
   1284                        &CurDadXmits
   1285                        );
   1286 
   1287         gBS->SetTimer (TimeOutEvt, TimerRelative, 50000000 + 10000000 * CurDadXmits);
   1288 
   1289         while (EFI_ERROR (gBS->CheckEvent (TimeOutEvt))) {
   1290           if (IsAddressOk) {
   1291             Status = EFI_SUCCESS;
   1292             break;
   1293           }
   1294         }
   1295       }
   1296 
   1297       IfCb->IfCfg->UnregisterDataNotify (
   1298                      IfCb->IfCfg,
   1299                      Ip6ConfigDataTypeManualAddress,
   1300                      MappedEvt
   1301                      );
   1302 
   1303       if (EFI_ERROR (Status)) {
   1304         ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_ERR_MAN_HOST), mHiiHandle, Status);
   1305         goto ON_EXIT;
   1306       }
   1307 
   1308       //
   1309       // Check whether the address is set successfully.
   1310       //
   1311       DataSize = 0;
   1312 
   1313       Status = IfCb->IfCfg->GetData (
   1314                               IfCb->IfCfg,
   1315                               Ip6ConfigDataTypeInterfaceInfo,
   1316                               &DataSize,
   1317                               NULL
   1318                               );
   1319 
   1320       if (Status != EFI_BUFFER_TOO_SMALL) {
   1321         ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_ERR_IP6CFG_GETDATA), mHiiHandle, Status);
   1322         goto ON_EXIT;
   1323       }
   1324 
   1325       IfInfo = AllocateZeroPool (DataSize);
   1326 
   1327       if (IfInfo == NULL) {
   1328         Status = EFI_OUT_OF_RESOURCES;
   1329         goto ON_EXIT;
   1330       }
   1331 
   1332       Status = IfCb->IfCfg->GetData (
   1333                               IfCb->IfCfg,
   1334                               Ip6ConfigDataTypeInterfaceInfo,
   1335                               &DataSize,
   1336                               IfInfo
   1337                               );
   1338 
   1339       if (EFI_ERROR (Status)) {
   1340         ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_ERR_IP6CFG_GETDATA), mHiiHandle, Status);
   1341         goto ON_EXIT;
   1342       }
   1343 
   1344       for ( Index = 0; Index < (UINTN) (AddrSize / sizeof (EFI_IP6_CONFIG_MANUAL_ADDRESS)); Index++) {
   1345         IsAddressSet = FALSE;
   1346         //
   1347         // By default, the prefix length 0 is regarded as 64.
   1348         //
   1349         if (CfgManAddr[Index].PrefixLength == 0) {
   1350           CfgManAddr[Index].PrefixLength = 64;
   1351         }
   1352 
   1353         for (Index2 = 0; Index2 < IfInfo->AddressInfoCount; Index2++) {
   1354           if (EFI_IP6_EQUAL (&IfInfo->AddressInfo[Index2].Address, &CfgManAddr[Index].Address) &&
   1355               (IfInfo->AddressInfo[Index2].PrefixLength == CfgManAddr[Index].PrefixLength)) {
   1356             IsAddressSet = TRUE;
   1357             break;
   1358           }
   1359         }
   1360 
   1361         if (!IsAddressSet) {
   1362           ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_ERR_ADDRESS_FAILED), mHiiHandle);
   1363           IfConfig6PrintIpAddr (
   1364             &CfgManAddr[Index].Address,
   1365             &CfgManAddr[Index].PrefixLength
   1366             );
   1367         }
   1368       }
   1369 
   1370     } else if (StrCmp (VarArg->Arg, L"gw") == 0) {
   1371       //
   1372       // Parse till the next tag or the end of command line.
   1373       //
   1374       VarArg = VarArg->Next;
   1375       Status = IfConfig6ParseGwDnsAddressList (
   1376                  &VarArg,
   1377                  &CfgAddr,
   1378                  &AddrSize
   1379                  );
   1380 
   1381       if (EFI_ERROR (Status)) {
   1382         if (Status == EFI_INVALID_PARAMETER) {
   1383           ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_ERR_LACK_ARGUMENTS), mHiiHandle, L"gw");
   1384           continue;
   1385         } else {
   1386           goto ON_EXIT;
   1387         }
   1388       }
   1389       //
   1390       // Set static gateway ip6 address list.
   1391       //
   1392       Status = IfCb->IfCfg->SetData (
   1393                               IfCb->IfCfg,
   1394                               Ip6ConfigDataTypeGateway,
   1395                               AddrSize,
   1396                               CfgAddr
   1397                               );
   1398 
   1399       if (EFI_ERROR (Status)) {
   1400         goto ON_EXIT;
   1401       }
   1402 
   1403     } else if (StrCmp (VarArg->Arg, L"dns") == 0) {
   1404       //
   1405       // Parse till the next tag or the end of command line.
   1406       //
   1407       VarArg = VarArg->Next;
   1408       Status = IfConfig6ParseGwDnsAddressList (
   1409                  &VarArg,
   1410                  &CfgAddr,
   1411                  &AddrSize
   1412                  );
   1413 
   1414       if (EFI_ERROR (Status)) {
   1415         if (Status == EFI_INVALID_PARAMETER) {
   1416           ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_ERR_LACK_ARGUMENTS), mHiiHandle, L"dns");
   1417           continue;
   1418         } else {
   1419           goto ON_EXIT;
   1420         }
   1421       }
   1422       //
   1423       // Set static dhs server ip6 address list.
   1424       //
   1425       Status = IfCb->IfCfg->SetData (
   1426                               IfCb->IfCfg,
   1427                               Ip6ConfigDataTypeDnsServer,
   1428                               AddrSize,
   1429                               CfgAddr
   1430                               );
   1431 
   1432       if (EFI_ERROR (Status)) {
   1433         goto ON_EXIT;
   1434       }
   1435 
   1436     } else if (StrCmp (VarArg->Arg, L"id") == 0) {
   1437       //
   1438       // Parse till the next tag or the end of command line.
   1439       //
   1440       VarArg = VarArg->Next;
   1441       Status = IfConfig6ParseInterfaceId (&VarArg, &InterfaceId);
   1442 
   1443       if (EFI_ERROR (Status)) {
   1444         goto ON_EXIT;
   1445       }
   1446       //
   1447       // Set alternative interface id.
   1448       //
   1449       Status = IfCb->IfCfg->SetData (
   1450                               IfCb->IfCfg,
   1451                               Ip6ConfigDataTypeAltInterfaceId,
   1452                               sizeof (EFI_IP6_CONFIG_INTERFACE_ID),
   1453                               InterfaceId
   1454                               );
   1455 
   1456       if (EFI_ERROR (Status)) {
   1457         goto ON_EXIT;
   1458       }
   1459 
   1460     } else if (StrCmp (VarArg->Arg, L"dad") == 0) {
   1461       //
   1462       // Parse till the next tag or the end of command line.
   1463       //
   1464       VarArg = VarArg->Next;
   1465       Status = IfConfig6ParseDadXmits (&VarArg, &DadXmits);
   1466 
   1467       if (EFI_ERROR (Status)) {
   1468         goto ON_EXIT;
   1469       }
   1470       //
   1471       // Set dad transmits count.
   1472       //
   1473       Status = IfCb->IfCfg->SetData (
   1474                               IfCb->IfCfg,
   1475                               Ip6ConfigDataTypeDupAddrDetectTransmits,
   1476                               sizeof (EFI_IP6_CONFIG_DUP_ADDR_DETECT_TRANSMITS),
   1477                               &DadXmits
   1478                               );
   1479 
   1480       if (EFI_ERROR(Status)) {
   1481         goto ON_EXIT;
   1482       }
   1483     }
   1484   }
   1485 
   1486 ON_EXIT:
   1487 
   1488   if (CfgManAddr != NULL) {
   1489     FreePool (CfgManAddr);
   1490   }
   1491 
   1492   if (CfgAddr != NULL) {
   1493     FreePool (CfgAddr);
   1494   }
   1495 
   1496   if (MappedEvt != NULL) {
   1497     gBS->CloseEvent (MappedEvt);
   1498   }
   1499 
   1500   if (TimeOutEvt != NULL) {
   1501     gBS->CloseEvent (TimeOutEvt);
   1502   }
   1503 
   1504   if (IfInfo != NULL) {
   1505     FreePool (IfInfo);
   1506   }
   1507 
   1508   return Status;
   1509 
   1510 }
   1511 
   1512 /**
   1513   The IfConfig6 main process.
   1514 
   1515   @param[in]   Private    The pointer of IFCONFIG6_PRIVATE_DATA.
   1516 
   1517   @retval EFI_SUCCESS    IfConfig6 processed successfully.
   1518   @retval others         The IfConfig6 process failed.
   1519 
   1520 **/
   1521 EFI_STATUS
   1522 IfConfig6 (
   1523   IN IFCONFIG6_PRIVATE_DATA    *Private
   1524   )
   1525 {
   1526   EFI_STATUS    Status;
   1527 
   1528   //
   1529   // Get configure information of all interfaces.
   1530   //
   1531   Status = IfConfig6GetInterfaceInfo (
   1532              Private->ImageHandle,
   1533              Private->IfName,
   1534              &Private->IfList
   1535              );
   1536 
   1537   if (EFI_ERROR (Status)) {
   1538     goto ON_EXIT;
   1539   }
   1540 
   1541   switch (Private->OpCode) {
   1542   case IfConfig6OpList:
   1543     Status = IfConfig6ShowInterfaceInfo (&Private->IfList);
   1544     break;
   1545 
   1546   case IfConfig6OpClear:
   1547     Status = IfConfig6ClearInterfaceInfo (&Private->IfList);
   1548     break;
   1549 
   1550   case IfConfig6OpSet:
   1551     Status = IfConfig6SetInterfaceInfo (&Private->IfList, Private->VarArg);
   1552     break;
   1553 
   1554   default:
   1555     Status = EFI_ABORTED;
   1556   }
   1557 
   1558 ON_EXIT:
   1559 
   1560   return Status;
   1561 }
   1562 
   1563 /**
   1564   The IfConfig6 cleanup process, free the allocated memory.
   1565 
   1566   @param[in]   Private    The pointer of  IFCONFIG6_PRIVATE_DATA.
   1567 
   1568 **/
   1569 VOID
   1570 IfConfig6Cleanup (
   1571   IN IFCONFIG6_PRIVATE_DATA    *Private
   1572   )
   1573 {
   1574   LIST_ENTRY                *Entry;
   1575   LIST_ENTRY                *NextEntry;
   1576   IFCONFIG6_INTERFACE_CB    *IfCb;
   1577   ARG_LIST                  *ArgNode;
   1578   ARG_LIST                  *ArgHead;
   1579 
   1580   ASSERT (Private != NULL);
   1581 
   1582   //
   1583   // Clean the list which save the set config Args.
   1584   //
   1585   if (Private->VarArg != NULL) {
   1586     ArgHead = Private->VarArg;
   1587 
   1588     while (ArgHead->Next != NULL) {
   1589       ArgNode = ArgHead->Next;
   1590       FreePool (ArgHead);
   1591       ArgHead = ArgNode;
   1592     }
   1593 
   1594     FreePool (ArgHead);
   1595   }
   1596 
   1597   if (Private->IfName != NULL)
   1598     FreePool (Private->IfName);
   1599 
   1600 
   1601   //
   1602   // Clean the IFCONFIG6_INTERFACE_CB list.
   1603   //
   1604   Entry     = Private->IfList.ForwardLink;
   1605   NextEntry = Entry->ForwardLink;
   1606 
   1607   while (Entry != &Private->IfList) {
   1608 
   1609     IfCb = BASE_CR (Entry, IFCONFIG6_INTERFACE_CB, Link);
   1610 
   1611     RemoveEntryList (&IfCb->Link);
   1612 
   1613     if (IfCb->IfId != NULL) {
   1614 
   1615       FreePool (IfCb->IfId);
   1616     }
   1617 
   1618     if (IfCb->IfInfo != NULL) {
   1619 
   1620       FreePool (IfCb->IfInfo);
   1621     }
   1622 
   1623     FreePool (IfCb);
   1624 
   1625     Entry     = NextEntry;
   1626     NextEntry = Entry->ForwardLink;
   1627   }
   1628 
   1629   FreePool (Private);
   1630 }
   1631 
   1632 /**
   1633   This is the declaration of an EFI image entry point. This entry point is
   1634   the same for UEFI Applications, UEFI OS Loaders, and UEFI Drivers, including
   1635   both device drivers and bus drivers.
   1636 
   1637   The entry point for the IfConfig6 application which parses the command line input and calls the IfConfig6 process.
   1638 
   1639   @param[in] ImageHandle    The image handle of this application.
   1640   @param[in] SystemTable    The pointer to the EFI System Table.
   1641 
   1642   @retval EFI_SUCCESS    The operation completed successfully.
   1643   @retval Others         Some errors occur.
   1644 
   1645 **/
   1646 EFI_STATUS
   1647 EFIAPI
   1648 IfConfig6Initialize (
   1649   IN  EFI_HANDLE         ImageHandle,
   1650   IN  EFI_SYSTEM_TABLE    *SystemTable
   1651   )
   1652 {
   1653   EFI_STATUS                    Status;
   1654   IFCONFIG6_PRIVATE_DATA        *Private;
   1655   EFI_HII_PACKAGE_LIST_HEADER   *PackageList;
   1656   LIST_ENTRY                    *ParamPackage;
   1657   CONST CHAR16                  *ValueStr;
   1658   ARG_LIST                      *ArgList;
   1659   CHAR16                        *ProblemParam;
   1660   CHAR16                        *Str;
   1661 
   1662   Private = NULL;
   1663 
   1664   //
   1665   // Retrieve HII package list from ImageHandle
   1666   //
   1667   Status = gBS->OpenProtocol (
   1668                   ImageHandle,
   1669                   &gEfiHiiPackageListProtocolGuid,
   1670                   (VOID **) &PackageList,
   1671                   ImageHandle,
   1672                   NULL,
   1673                   EFI_OPEN_PROTOCOL_GET_PROTOCOL
   1674                   );
   1675   if (EFI_ERROR (Status)) {
   1676     return Status;
   1677   }
   1678 
   1679   //
   1680   // Publish HII package list to HII Database.
   1681   //
   1682   Status = gHiiDatabase->NewPackageList (
   1683                           gHiiDatabase,
   1684                           PackageList,
   1685                           NULL,
   1686                           &mHiiHandle
   1687                           );
   1688   if (EFI_ERROR (Status)) {
   1689     return Status;
   1690   }
   1691 
   1692   ASSERT (mHiiHandle != NULL);
   1693 
   1694   Status = ShellCommandLineParseEx (mIfConfig6CheckList, &ParamPackage, &ProblemParam, TRUE, FALSE);
   1695   if (EFI_ERROR (Status)) {
   1696     ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_ERR_INVALID_COMMAND), mHiiHandle, ProblemParam);
   1697     goto ON_EXIT;
   1698   }
   1699 
   1700   //
   1701   // To handle no option.
   1702   //
   1703   if (!ShellCommandLineGetFlag (ParamPackage, L"-r") && !ShellCommandLineGetFlag (ParamPackage, L"-s") &&
   1704       !ShellCommandLineGetFlag (ParamPackage, L"-l")) {
   1705     ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_LACK_OPTION), mHiiHandle);
   1706     goto ON_EXIT;
   1707   }
   1708   //
   1709   // To handle conflict options.
   1710   //
   1711   if (((ShellCommandLineGetFlag (ParamPackage, L"-r")) && (ShellCommandLineGetFlag (ParamPackage, L"-s"))) ||
   1712       ((ShellCommandLineGetFlag (ParamPackage, L"-r")) && (ShellCommandLineGetFlag (ParamPackage, L"-l"))) ||
   1713       ((ShellCommandLineGetFlag (ParamPackage, L"-s")) && (ShellCommandLineGetFlag (ParamPackage, L"-l")))) {
   1714     ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_CONFLICT_OPTIONS), mHiiHandle);
   1715     goto ON_EXIT;
   1716   }
   1717 
   1718   Status = EFI_INVALID_PARAMETER;
   1719 
   1720   Private = AllocateZeroPool (sizeof (IFCONFIG6_PRIVATE_DATA));
   1721 
   1722   if (Private == NULL) {
   1723     Status = EFI_OUT_OF_RESOURCES;
   1724     goto ON_EXIT;
   1725   }
   1726 
   1727   InitializeListHead (&Private->IfList);
   1728 
   1729   //
   1730   // To get interface name for the list option.
   1731   //
   1732   if (ShellCommandLineGetFlag (ParamPackage, L"-l")) {
   1733     Private->OpCode = IfConfig6OpList;
   1734     ValueStr = ShellCommandLineGetValue (ParamPackage, L"-l");
   1735     if (ValueStr != NULL) {
   1736       Str             = AllocateCopyPool (StrSize (ValueStr), ValueStr);
   1737       ASSERT (Str != NULL);
   1738       Private->IfName = Str;
   1739     }
   1740   }
   1741   //
   1742   // To get interface name for the clear option.
   1743   //
   1744   if (ShellCommandLineGetFlag (ParamPackage, L"-r")) {
   1745     Private->OpCode = IfConfig6OpClear;
   1746     ValueStr = ShellCommandLineGetValue (ParamPackage, L"-r");
   1747     if (ValueStr != NULL) {
   1748       Str             = AllocateCopyPool (StrSize (ValueStr), ValueStr);
   1749       ASSERT (Str != NULL);
   1750       Private->IfName = Str;
   1751     }
   1752   }
   1753   //
   1754   // To get interface name and corresponding Args for the set option.
   1755   //
   1756   if (ShellCommandLineGetFlag (ParamPackage, L"-s")) {
   1757 
   1758     ValueStr = ShellCommandLineGetValue (ParamPackage, L"-s");
   1759     if (ValueStr == NULL) {
   1760       ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_ERR_LACK_INTERFACE), mHiiHandle);
   1761       goto ON_EXIT;
   1762     }
   1763     //
   1764     // To split the configuration into multi-section.
   1765     //
   1766     ArgList         = SplitStrToList (ValueStr, L' ');
   1767     ASSERT (ArgList != NULL);
   1768 
   1769     Private->OpCode = IfConfig6OpSet;
   1770     Private->IfName = ArgList->Arg;
   1771 
   1772     Private->VarArg = ArgList->Next;
   1773 
   1774     if (Private->IfName == NULL || Private->VarArg == NULL) {
   1775       ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_ERR_LACK_COMMAND), mHiiHandle);
   1776       goto ON_EXIT;
   1777     }
   1778   }
   1779   //
   1780   // Main process of ifconfig6.
   1781   //
   1782   Status = IfConfig6 (Private);
   1783 
   1784 ON_EXIT:
   1785 
   1786   ShellCommandLineFreeVarList (ParamPackage);
   1787   HiiRemovePackages (mHiiHandle);
   1788   if (Private != NULL)
   1789     IfConfig6Cleanup (Private);
   1790 
   1791   return Status;
   1792 }
   1793 
   1794