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