• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 *
SplitStrToList(IN CONST CHAR16 * String,IN CHAR16 Separator)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
IfConfig6RetriveCheckListByName(IN VAR_CHECK_ITEM * CheckList,IN CHAR16 * Name,IN BOOLEAN Init)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
IfConfig6ManualAddressNotify(IN EFI_EVENT Event,IN VOID * Context)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
IfConfig6PrintMacAddr(IN UINT8 * Node,IN UINT32 Size)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
IfConfig6PrintIpAddr(IN EFI_IPv6_ADDRESS * Ip,IN UINT8 * PrefixLen)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
IfConfig6ParseManualAddressList(IN OUT ARG_LIST ** Arg,OUT EFI_IP6_CONFIG_MANUAL_ADDRESS ** Buf,OUT UINTN * BufSize)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
IfConfig6ParseGwDnsAddressList(IN OUT ARG_LIST ** Arg,OUT EFI_IPv6_ADDRESS ** Buf,OUT UINTN * BufSize)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
IfConfig6ParseInterfaceId(IN OUT ARG_LIST ** Arg,OUT EFI_IP6_CONFIG_INTERFACE_ID ** IfId)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
IfConfig6ParseDadXmits(IN OUT ARG_LIST ** Arg,OUT UINT32 * Xmits)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
IfConfig6GetInterfaceInfo(IN EFI_HANDLE ImageHandle,IN CHAR16 * IfName,IN LIST_ENTRY * IfList)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
IfConfig6ShowInterfaceInfo(IN LIST_ENTRY * IfList)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
IfConfig6ClearInterfaceInfo(IN LIST_ENTRY * IfList)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
IfConfig6SetInterfaceInfo(IN LIST_ENTRY * IfList,IN ARG_LIST * VarArg)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
IfConfig6(IN IFCONFIG6_PRIVATE_DATA * Private)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
IfConfig6Cleanup(IN IFCONFIG6_PRIVATE_DATA * Private)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
IfConfig6Initialize(IN EFI_HANDLE ImageHandle,IN EFI_SYSTEM_TABLE * SystemTable)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