]> git.proxmox.com Git - mirror_edk2.git/blob - NetworkPkg/Ip6Dxe/Ip6ConfigNv.c
NetworkPkg: Replace BSD License with BSD+Patent License
[mirror_edk2.git] / NetworkPkg / Ip6Dxe / Ip6ConfigNv.c
1 /** @file
2 Helper functions for configuring or obtaining the parameters relating to IP6.
3
4 Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved.<BR>
5
6 SPDX-License-Identifier: BSD-2-Clause-Patent
7
8 **/
9
10 #include "Ip6Impl.h"
11
12 CHAR16 mIp6ConfigStorageName[] = L"IP6_CONFIG_IFR_NVDATA";
13
14 /**
15 The notify function of create event when performing a manual configuration.
16
17 @param[in] Event The pointer of Event.
18 @param[in] Context The pointer of Context.
19
20 **/
21 VOID
22 EFIAPI
23 Ip6ConfigManualAddressNotify (
24 IN EFI_EVENT Event,
25 IN VOID *Context
26 )
27 {
28 *((BOOLEAN *) Context) = TRUE;
29 }
30
31 /**
32 Get the configuration data for the EFI IPv6 network stack running on the
33 communication. It is a help function to the call EfiIp6ConfigGetData().
34
35 @param[in] Ip6Config The pointer to the EFI_IP6_CONFIG_PROTOCOL instance.
36 @param[in] DataType The type of data to get.
37 @param[out] DataSize The size of buffer required in bytes.
38 @param[out] Data The data buffer in which the configuration data is returned. The
39 type of the data buffer associated with the DataType.
40 It is the caller's responsibility to free the resource.
41
42 @retval EFI_SUCCESS The specified configuration data was obtained successfully.
43 @retval EFI_INVALID_PARAMETER One or more of the followings are TRUE:
44 - Ip6Config is NULL or invalid.
45 - DataSize is NULL.
46 - Data is NULL.
47 @retval EFI_OUT_OF_RESOURCES Fail to perform the operation due to lack of resources.
48 @retval EFI_NOT_READY The specified configuration data is not ready due to an
49 asynchronous configuration process already in progress.
50 @retval EFI_NOT_FOUND The specified configuration data was not found.
51
52 **/
53 EFI_STATUS
54 Ip6ConfigNvGetData (
55 IN EFI_IP6_CONFIG_PROTOCOL *Ip6Config,
56 IN EFI_IP6_CONFIG_DATA_TYPE DataType,
57 OUT UINTN *DataSize,
58 OUT VOID **Data
59 )
60 {
61 UINTN BufferSize;
62 VOID *Buffer;
63 EFI_STATUS Status;
64
65 if ((Ip6Config == NULL) || (Data == NULL) || (DataSize == NULL)) {
66 return EFI_INVALID_PARAMETER;
67 }
68
69 BufferSize = 0;
70 Status = Ip6Config->GetData (
71 Ip6Config,
72 DataType,
73 &BufferSize,
74 NULL
75 );
76 if (Status != EFI_BUFFER_TOO_SMALL) {
77 return Status;
78 }
79
80 Buffer = AllocateZeroPool (BufferSize);
81 if (Buffer == NULL) {
82 return EFI_OUT_OF_RESOURCES;
83 }
84
85 Status = Ip6Config->GetData (
86 Ip6Config,
87 DataType,
88 &BufferSize,
89 Buffer
90 );
91 if (EFI_ERROR (Status)) {
92 FreePool (Buffer);
93 return Status;
94 }
95
96 *DataSize = BufferSize;
97 *Data = Buffer;
98
99 return EFI_SUCCESS;
100 }
101
102 /**
103 Free all nodes in IP6_ADDRESS_INFO_ENTRY in the list array specified
104 with ListHead.
105
106 @param[in] ListHead The head of the list array in IP6_ADDRESS_INFO_ENTRY.
107
108 **/
109 VOID
110 Ip6FreeAddressInfoList (
111 IN LIST_ENTRY *ListHead
112 )
113 {
114 IP6_ADDRESS_INFO_ENTRY *Node;
115 LIST_ENTRY *Entry;
116 LIST_ENTRY *NextEntry;
117
118 NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, ListHead) {
119 Node = NET_LIST_USER_STRUCT (Entry, IP6_ADDRESS_INFO_ENTRY, Link);
120 RemoveEntryList (&Node->Link);
121 FreePool (Node);
122 }
123 }
124
125 /**
126 Convert the IPv6 address into a formatted string.
127
128 @param[in] Ip6 The IPv6 address.
129 @param[out] Str The formatted IP string.
130
131 **/
132 VOID
133 Ip6ToStr (
134 IN EFI_IPv6_ADDRESS *Ip6,
135 OUT CHAR16 *Str
136 )
137 {
138 UINTN Index;
139 BOOLEAN Short;
140 UINTN Number;
141 CHAR16 FormatString[8];
142
143 Short = FALSE;
144
145 for (Index = 0; Index < 15; Index = Index + 2) {
146 if (!Short &&
147 Index % 2 == 0 &&
148 Ip6->Addr[Index] == 0 &&
149 Ip6->Addr[Index + 1] == 0
150 ) {
151 //
152 // Deal with the case of ::.
153 //
154 if (Index == 0) {
155 *Str = L':';
156 *(Str + 1) = L':';
157 Str = Str + 2;
158 } else {
159 *Str = L':';
160 Str = Str + 1;
161 }
162
163 while ((Index < 15) && (Ip6->Addr[Index] == 0) && (Ip6->Addr[Index + 1] == 0)) {
164 Index = Index + 2;
165 }
166
167 Short = TRUE;
168
169 if (Index == 16) {
170 //
171 // :: is at the end of the address.
172 //
173 *Str = L'\0';
174 break;
175 }
176 }
177
178 ASSERT (Index < 15);
179
180 if (Ip6->Addr[Index] == 0) {
181 Number = UnicodeSPrint (Str, 2 * IP6_STR_MAX_SIZE, L"%x:", (UINTN) Ip6->Addr[Index + 1]);
182 } else {
183 if (Ip6->Addr[Index + 1] < 0x10) {
184 CopyMem (FormatString, L"%x0%x:", StrSize (L"%x0%x:"));
185 } else {
186 CopyMem (FormatString, L"%x%x:", StrSize (L"%x%x:"));
187 }
188
189 Number = UnicodeSPrint (
190 Str,
191 2 * IP6_STR_MAX_SIZE,
192 (CONST CHAR16 *) FormatString,
193 (UINTN) Ip6->Addr[Index],
194 (UINTN) Ip6->Addr[Index + 1]
195 );
196 }
197
198 Str = Str + Number;
199
200 if (Index + 2 == 16) {
201 *Str = L'\0';
202 if (*(Str - 1) == L':') {
203 *(Str - 1) = L'\0';
204 }
205 }
206 }
207 }
208
209 /**
210 Convert EFI_IP6_CONFIG_INTERFACE_ID to string format.
211
212 @param[out] String The buffer to store the converted string.
213 @param[in] IfId The pointer of EFI_IP6_CONFIG_INTERFACE_ID.
214
215 @retval EFI_SUCCESS The string converted successfully.
216 @retval EFI_INVALID_PARAMETER Any input parameter is invalid.
217
218 **/
219 EFI_STATUS
220 Ip6ConvertInterfaceIdToString (
221 OUT CHAR16 *String,
222 IN EFI_IP6_CONFIG_INTERFACE_ID *IfId
223 )
224 {
225 UINT8 Index;
226 UINTN Number;
227
228 if ((String == NULL) || (IfId == NULL)) {
229 return EFI_INVALID_PARAMETER;
230 }
231
232 for (Index = 0; Index < 8; Index++) {
233 Number = UnicodeSPrint (
234 String,
235 2 * INTERFACE_ID_STR_STORAGE,
236 L"%x:",
237 (UINTN) IfId->Id[Index]
238 );
239 String = String + Number;
240 }
241
242 *(String - 1) = '\0';
243
244 return EFI_SUCCESS;
245 }
246
247 /**
248 Parse InterfaceId in string format and convert it to EFI_IP6_CONFIG_INTERFACE_ID.
249
250 @param[in] String The buffer of the string to be parsed.
251 @param[out] IfId The pointer of EFI_IP6_CONFIG_INTERFACE_ID.
252
253 @retval EFI_SUCCESS The operation finished successfully.
254 @retval EFI_INVALID_PARAMETER Any input parameter is invalid.
255
256 **/
257 EFI_STATUS
258 Ip6ParseInterfaceIdFromString (
259 IN CONST CHAR16 *String,
260 OUT EFI_IP6_CONFIG_INTERFACE_ID *IfId
261 )
262 {
263 UINT8 Index;
264 CHAR16 *IfIdStr;
265 CHAR16 *TempStr;
266 UINTN NodeVal;
267
268 if ((String == NULL) || (IfId == NULL)) {
269 return EFI_INVALID_PARAMETER;
270 }
271
272 IfIdStr = (CHAR16 *) String;
273
274 ZeroMem (IfId, sizeof (EFI_IP6_CONFIG_INTERFACE_ID));
275
276 for (Index = 0; Index < 8; Index++) {
277 TempStr = IfIdStr;
278
279 while ((*IfIdStr != L'\0') && (*IfIdStr != L':')) {
280 IfIdStr++;
281 }
282
283 //
284 // The InterfaceId format is X:X:X:X, the number of X should not exceed 8.
285 // If the number of X is less than 8, zero is appended to the InterfaceId.
286 //
287 if ((*IfIdStr == ':') && (Index == 7)) {
288 return EFI_INVALID_PARAMETER;
289 }
290
291 //
292 // Convert the string to interface id. AsciiStrHexToUintn stops at the
293 // first character that is not a valid hex character, ':' or '\0' here.
294 //
295 NodeVal = StrHexToUintn (TempStr);
296 if (NodeVal > 0xFF) {
297 return EFI_INVALID_PARAMETER;
298 }
299
300 IfId->Id[Index] = (UINT8) NodeVal;
301
302 IfIdStr++;
303 }
304
305 return EFI_SUCCESS;
306 }
307
308 /**
309 Create Hii Extend Label OpCode as the start opcode and end opcode. It is
310 a help function.
311
312 @param[in] StartLabelNumber The number of start label.
313 @param[out] StartOpCodeHandle Points to the start opcode handle.
314 @param[out] StartLabel Points to the created start opcode.
315 @param[out] EndOpCodeHandle Points to the end opcode handle.
316 @param[out] EndLabel Points to the created end opcode.
317
318 @retval EFI_OUT_OF_RESOURCES Does not have sufficient resources to finish this
319 operation.
320 @retval EFI_INVALID_PARAMETER Any input parameter is invalid.
321 @retval EFI_SUCCESS The operation completed successfully.
322
323 **/
324 EFI_STATUS
325 Ip6CreateOpCode (
326 IN UINT16 StartLabelNumber,
327 OUT VOID **StartOpCodeHandle,
328 OUT EFI_IFR_GUID_LABEL **StartLabel,
329 OUT VOID **EndOpCodeHandle,
330 OUT EFI_IFR_GUID_LABEL **EndLabel
331 )
332 {
333 EFI_STATUS Status;
334 EFI_IFR_GUID_LABEL *InternalStartLabel;
335 EFI_IFR_GUID_LABEL *InternalEndLabel;
336
337 if (StartOpCodeHandle == NULL || StartLabel == NULL || EndOpCodeHandle == NULL || EndLabel == NULL) {
338 return EFI_INVALID_PARAMETER;
339 }
340
341 *StartOpCodeHandle = NULL;
342 *EndOpCodeHandle = NULL;
343 Status = EFI_OUT_OF_RESOURCES;
344
345 //
346 // Initialize the container for dynamic opcodes.
347 //
348 *StartOpCodeHandle = HiiAllocateOpCodeHandle ();
349 if (*StartOpCodeHandle == NULL) {
350 return Status;
351 }
352
353 *EndOpCodeHandle = HiiAllocateOpCodeHandle ();
354 if (*EndOpCodeHandle == NULL) {
355 goto Exit;
356 }
357
358 //
359 // Create Hii Extend Label OpCode as the start opcode.
360 //
361 InternalStartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (
362 *StartOpCodeHandle,
363 &gEfiIfrTianoGuid,
364 NULL,
365 sizeof (EFI_IFR_GUID_LABEL)
366 );
367 if (InternalStartLabel == NULL) {
368 goto Exit;
369 }
370
371 InternalStartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
372 InternalStartLabel->Number = StartLabelNumber;
373
374 //
375 // Create Hii Extend Label OpCode as the end opcode.
376 //
377 InternalEndLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (
378 *EndOpCodeHandle,
379 &gEfiIfrTianoGuid,
380 NULL,
381 sizeof (EFI_IFR_GUID_LABEL)
382 );
383 if (InternalEndLabel == NULL) {
384 goto Exit;
385 }
386
387 InternalEndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
388 InternalEndLabel->Number = LABEL_END;
389
390 *StartLabel = InternalStartLabel;
391 *EndLabel = InternalEndLabel;
392
393 return EFI_SUCCESS;
394
395 Exit:
396
397 if (*StartOpCodeHandle != NULL) {
398 HiiFreeOpCodeHandle (*StartOpCodeHandle);
399 }
400
401 if (*EndOpCodeHandle != NULL) {
402 HiiFreeOpCodeHandle (*EndOpCodeHandle);
403 }
404
405 return Status;
406 }
407
408 /**
409 This function converts the different format of address list to string format and
410 then generates the corresponding text opcode to illustarate the address info in
411 IP6 configuration page. Currently, the following formats are supported:
412 EFI_IP6_ADDRESS_INFO AddressType: Ip6ConfigNvHostAddress;
413 EFI_IPv6_ADDRESS AddressType: Ip6ConfigNvGatewayAddress and Ip6ConfigNvDnsAddress;
414 EFI_IP6_ROUTE_TABLE AddressType: Ip6ConfigNvRouteTable.
415
416 @param[in, out] String The pointer to the buffer to store the converted
417 string.
418 @param[in] HiiHandle A handle that was previously registered in the
419 HII Database.
420 @param[in] AddressType The address type.
421 @param[in] AddressInfo Pointer to the address list.
422 @param[in] AddressCount The address count of the address list.
423
424 @retval EFI_SUCCESS The operation finished successfully.
425 @retval EFI_INVALID_PARAMETER Any input parameter is invalid.
426 @retval EFI_UNSUPPORTED The AddressType is not supported.
427
428
429 **/
430 EFI_STATUS
431 Ip6ConvertAddressListToString (
432 IN OUT CHAR16 *String,
433 IN EFI_HII_HANDLE HiiHandle,
434 IN IP6_CONFIG_NV_ADDRESS_TYPE AddressType,
435 IN VOID *AddressInfo,
436 IN UINTN AddressCount
437 )
438 {
439 UINTN Index;
440 UINTN Number;
441 CHAR16 *TempStr;
442 EFI_STATUS Status;
443 VOID *StartOpCodeHandle;
444 EFI_IFR_GUID_LABEL *StartLabel;
445 VOID *EndOpCodeHandle;
446 EFI_IFR_GUID_LABEL *EndLabel;
447 UINT16 StartLabelNumber;
448 EFI_STRING_ID TextTwo;
449 UINT8 *AddressHead;
450 UINT8 PrefixLength;
451 EFI_IPv6_ADDRESS *Address;
452
453 if ((String == NULL) || (HiiHandle == NULL) || (AddressInfo == NULL)) {
454 return EFI_INVALID_PARAMETER;
455 }
456
457 if (AddressType == Ip6ConfigNvHostAddress) {
458 StartLabelNumber = HOST_ADDRESS_LABEL;
459 } else if (AddressType == Ip6ConfigNvGatewayAddress) {
460 StartLabelNumber = GATEWAY_ADDRESS_LABEL;
461 } else if (AddressType == Ip6ConfigNvDnsAddress) {
462 StartLabelNumber = DNS_ADDRESS_LABEL;
463 } else if (AddressType == Ip6ConfigNvRouteTable) {
464 StartLabelNumber = ROUTE_TABLE_LABEL;
465 } else {
466 ASSERT (FALSE);
467 return EFI_UNSUPPORTED;
468 }
469
470 Status = Ip6CreateOpCode (
471 StartLabelNumber,
472 &StartOpCodeHandle,
473 &StartLabel,
474 &EndOpCodeHandle,
475 &EndLabel
476 );
477 if (EFI_ERROR (Status)) {
478 return Status;
479 }
480
481 AddressHead = (UINT8 *) AddressInfo;
482
483 for (Index = 0; Index < AddressCount; Index++) {
484 if (AddressType == Ip6ConfigNvHostAddress) {
485 AddressInfo = AddressHead + sizeof (EFI_IP6_ADDRESS_INFO) * Index;
486 Address = &((EFI_IP6_ADDRESS_INFO *) AddressInfo)->Address;
487 } else if (AddressType == Ip6ConfigNvRouteTable) {
488 AddressInfo = AddressHead + sizeof (EFI_IP6_ROUTE_TABLE) * Index;
489 Address = &((EFI_IP6_ROUTE_TABLE *) AddressInfo)->Destination;
490 } else {
491 AddressInfo = AddressHead + sizeof (EFI_IPv6_ADDRESS) * Index;
492 Address = AddressInfo;
493 }
494
495 //
496 // Convert the IP address info to string.
497 //
498 Ip6ToStr (Address, String);
499 TempStr = String + StrLen (String);
500
501 if ((AddressType == Ip6ConfigNvHostAddress) || (AddressType == Ip6ConfigNvRouteTable)) {
502 if (AddressType == Ip6ConfigNvHostAddress) {
503 PrefixLength = ((EFI_IP6_ADDRESS_INFO *) AddressInfo)->PrefixLength;
504 } else {
505 PrefixLength = ((EFI_IP6_ROUTE_TABLE *) AddressInfo)->PrefixLength;
506 }
507
508 //
509 // Append the prefix length to the string.
510 //
511 *TempStr = L'/';
512 TempStr++;
513 Number = UnicodeSPrint (TempStr, 6, L"%d", PrefixLength);
514 TempStr = TempStr + Number;
515 }
516
517 if (AddressType == Ip6ConfigNvRouteTable) {
518 //
519 // Append " >> " to the string.
520 //
521 Number = UnicodeSPrint (TempStr, 8, L" >> ");
522 TempStr = TempStr + Number;
523
524 //
525 // Append the gateway address to the string.
526 //
527 Ip6ToStr (&((EFI_IP6_ROUTE_TABLE *) AddressInfo)->Gateway, TempStr);
528 TempStr = TempStr + StrLen (TempStr);
529 }
530
531 //
532 // Generate a text opcode and update the UI.
533 //
534 TextTwo = HiiSetString (HiiHandle, 0, String, NULL);
535 if (TextTwo == 0) {
536 Status = EFI_INVALID_PARAMETER;
537 goto Exit;
538 }
539
540 HiiCreateTextOpCode (StartOpCodeHandle, STR_NULL, STR_NULL, TextTwo);
541
542 String = TempStr;
543 *String = IP6_ADDRESS_DELIMITER;
544 String++;
545 }
546
547 *(String - 1) = '\0';
548
549 Status = HiiUpdateForm (
550 HiiHandle, // HII handle
551 &gIp6ConfigNvDataGuid, // Formset GUID
552 FORMID_MAIN_FORM, // Form ID
553 StartOpCodeHandle, // Label for where to insert opcodes
554 EndOpCodeHandle // Replace data
555 );
556
557 Exit:
558 HiiFreeOpCodeHandle (StartOpCodeHandle);
559 HiiFreeOpCodeHandle (EndOpCodeHandle);
560
561 return Status;
562 }
563
564 /**
565 Parse address list in string format and convert it to a list array of node in
566 IP6_ADDRESS_INFO_ENTRY.
567
568 @param[in] String The buffer to string to be parsed.
569 @param[out] ListHead The list head of array.
570 @param[out] AddressCount The number of list nodes in the array.
571
572 @retval EFI_SUCCESS The operation finished successfully.
573 @retval EFI_INVALID_PARAMETER Any input parameter is invalid.
574 @retval EFI_OUT_OF_RESOURCES Failed to perform the operation due to lack of resource.
575
576 **/
577 EFI_STATUS
578 Ip6ParseAddressListFromString (
579 IN CONST CHAR16 *String,
580 OUT LIST_ENTRY *ListHead,
581 OUT UINT32 *AddressCount
582 )
583 {
584 EFI_STATUS Status;
585 CHAR16 *LocalString;
586 CHAR16 *Temp;
587 CHAR16 *TempStr;
588 EFI_IP6_ADDRESS_INFO AddressInfo;
589 IP6_ADDRESS_INFO_ENTRY *Node;
590 BOOLEAN Last;
591 UINT32 Count;
592
593 if ((String == NULL) || (ListHead == NULL) || (AddressCount == NULL)) {
594 return EFI_INVALID_PARAMETER;
595 }
596
597 ZeroMem (&AddressInfo, sizeof (EFI_IP6_ADDRESS_INFO));
598 LocalString = (CHAR16 *) AllocateCopyPool (StrSize (String), String);
599 if (LocalString == NULL) {
600 return EFI_OUT_OF_RESOURCES;
601 }
602
603 //
604 // Clean the original address list.
605 //
606 Ip6FreeAddressInfoList (ListHead);
607
608 Temp = LocalString;
609 Last = FALSE;
610 Count = 0;
611
612 while (*LocalString != L'\0') {
613 TempStr = LocalString;
614 while ((*LocalString != L'\0') && (*LocalString != IP6_ADDRESS_DELIMITER)) {
615 LocalString++;
616 }
617
618 if (*LocalString == L'\0') {
619 Last = TRUE;
620 }
621
622 *LocalString = L'\0';
623
624 Status = NetLibStrToIp6andPrefix (TempStr, &AddressInfo.Address, &AddressInfo.PrefixLength);
625 if (EFI_ERROR (Status)) {
626 goto Error;
627 }
628
629 if (AddressInfo.PrefixLength == 0xFF) {
630 AddressInfo.PrefixLength = 0;
631 }
632
633 if (!NetIp6IsValidUnicast (&AddressInfo.Address)) {
634 Status = EFI_INVALID_PARAMETER;
635 goto Error;
636 }
637
638 Node = AllocatePool (sizeof (IP6_ADDRESS_INFO_ENTRY));
639 if (Node == NULL) {
640 Status = EFI_OUT_OF_RESOURCES;
641 goto Error;
642 }
643
644 CopyMem (&Node->AddrInfo, &AddressInfo, sizeof (EFI_IP6_ADDRESS_INFO));
645 InsertTailList (ListHead, &Node->Link);
646 Count++;
647
648 if (Last) {
649 break;
650 }
651
652 LocalString++;
653 }
654
655 FreePool (Temp);
656 *AddressCount = Count;
657 return EFI_SUCCESS;
658
659 Error:
660 Ip6FreeAddressInfoList (ListHead);
661 FreePool (Temp);
662 return Status;
663 }
664
665 /**
666 This function converts the interface info to string and draws it to the IP6 UI.
667 The interface information includes interface name, interface type, hardware
668 address and route table information.
669
670 @param[in] IfInfo The pointer of EFI_IP6_CONFIG_INTERFACE_INFO.
671 @param[in] HiiHandle The handle that was previously registered in the
672 HII Database.
673 @param[in, out] IfrNvData Points to IP6_CONFIG_IFR_NVDATA.
674
675 @retval EFI_SUCCESS The operation finished successfully.
676 @retval EFI_INVALID_PARAMETER Any input parameter is invalid.
677 @retval EFI_OUT_OF_RESOURCES The operation failed due to lack of resources.
678
679 **/
680 EFI_STATUS
681 Ip6ConvertInterfaceInfoToString (
682 IN EFI_IP6_CONFIG_INTERFACE_INFO *IfInfo,
683 IN EFI_HII_HANDLE HiiHandle,
684 IN OUT IP6_CONFIG_IFR_NVDATA *IfrNvData
685 )
686 {
687 UINT32 Index;
688 UINTN Number;
689 CHAR16 *String;
690 CHAR16 PortString[ADDRESS_STR_MAX_SIZE];
691 CHAR16 FormatString[8];
692 EFI_STRING_ID StringId;
693
694 if ((IfInfo == NULL) || (HiiHandle == NULL) || (IfrNvData == NULL)) {
695 return EFI_INVALID_PARAMETER;
696 }
697
698 //
699 // Print the interface name.
700 //
701 StringId = HiiSetString (
702 HiiHandle,
703 STRING_TOKEN (STR_IP6_INTERFACE_NAME_CONTENT),
704 IfInfo->Name,
705 NULL
706 );
707 if (StringId == 0) {
708 return EFI_OUT_OF_RESOURCES;
709 }
710
711 //
712 // Print the interface type.
713 //
714 if (IfInfo->IfType == Ip6InterfaceTypeEthernet) {
715 CopyMem (PortString, IP6_ETHERNET, sizeof (IP6_ETHERNET));
716 } else if (IfInfo->IfType == Ip6InterfaceTypeExperimentalEthernet) {
717 CopyMem (PortString, IP6_EXPERIMENTAL_ETHERNET, sizeof (IP6_EXPERIMENTAL_ETHERNET));
718 } else {
719 //
720 // Refer to RFC1700, chapter Number Hardware Type.
721 //
722 UnicodeSPrint (PortString, 6, L"%d", IfInfo->IfType);
723 }
724
725 StringId = HiiSetString (
726 HiiHandle,
727 STRING_TOKEN (STR_IP6_INTERFACE_TYPE_CONTENT),
728 PortString,
729 NULL
730 );
731 if (StringId == 0) {
732 return EFI_OUT_OF_RESOURCES;
733 }
734
735 //
736 // Convert the hardware address.
737 //
738 String = PortString;
739 ASSERT (IfInfo->HwAddressSize <= 32);
740
741 for (Index = 0; Index < IfInfo->HwAddressSize; Index++) {
742
743 if (IfInfo->HwAddress.Addr[Index] < 0x10) {
744 CopyMem (FormatString, L"0%x-", sizeof (L"0%x-"));
745 } else {
746 CopyMem (FormatString, L"%x-", sizeof (L"%x-"));
747 }
748
749 Number = UnicodeSPrint (
750 String,
751 8,
752 (CONST CHAR16 *) FormatString,
753 (UINTN) IfInfo->HwAddress.Addr[Index]
754 );
755 String = String + Number;
756 }
757
758 if (Index != 0) {
759 ASSERT (String > PortString);
760 String--;
761 *String = '\0';
762 }
763
764 //
765 // Print the hardware address.
766 //
767 StringId = HiiSetString (
768 HiiHandle,
769 STRING_TOKEN (STR_IP6_MAC_ADDRESS_CONTENT),
770 PortString,
771 NULL
772 );
773 if (StringId == 0) {
774 return EFI_OUT_OF_RESOURCES;
775 }
776
777 return EFI_SUCCESS;
778 }
779
780 /**
781 Build the address info list from list array of node in IP6_ADDRESS_INFO_ENTRY.
782
783 @param[in] Instance Points to IP6 config instance data.
784 @param[in] AddressType The address type.
785 @param[out] AddressInfo The pointer to the buffer to store the address list.
786 @param[out] AddressSize The address size of the address list.
787
788 @retval EFI_SUCCESS The operation finished successfully.
789 @retval EFI_INVALID_PARAMETER Any input parameter is invalid.
790 @retval EFI_UNSUPPORTED The AddressType is not supported.
791
792 **/
793 EFI_STATUS
794 Ip6BuildNvAddressInfo (
795 IN IP6_CONFIG_INSTANCE *Instance,
796 IN IP6_CONFIG_NV_ADDRESS_TYPE AddressType,
797 OUT VOID **AddressInfo,
798 OUT UINTN *AddressSize
799 )
800 {
801 IP6_CONFIG_NVDATA *Ip6NvData;
802 LIST_ENTRY *Entry;
803 LIST_ENTRY *ListHead;
804 IP6_ADDRESS_INFO_ENTRY *Node;
805 VOID *AddressList;
806 VOID *TmpStr;
807 UINTN DataSize;
808 EFI_IPv6_ADDRESS *Ip6Address;
809 EFI_IP6_CONFIG_MANUAL_ADDRESS *ManualAddress;
810
811 if ((Instance == NULL) || (AddressInfo == NULL) || (AddressSize == NULL)) {
812 return EFI_INVALID_PARAMETER;
813 }
814
815 NET_CHECK_SIGNATURE (Instance, IP6_CONFIG_INSTANCE_SIGNATURE);
816
817 Ip6NvData = &Instance->Ip6NvData;
818
819 if (AddressType == Ip6ConfigNvHostAddress) {
820 ListHead = &Ip6NvData->ManualAddress;
821 DataSize = sizeof (EFI_IP6_CONFIG_MANUAL_ADDRESS) * Ip6NvData->ManualAddressCount;
822 } else if (AddressType == Ip6ConfigNvGatewayAddress) {
823 ListHead = &Ip6NvData->GatewayAddress;
824 DataSize = sizeof (EFI_IPv6_ADDRESS) * Ip6NvData->GatewayAddressCount;
825 } else if (AddressType == Ip6ConfigNvDnsAddress) {
826 ListHead = &Ip6NvData->DnsAddress;
827 DataSize = sizeof (EFI_IPv6_ADDRESS) * Ip6NvData->DnsAddressCount;
828 } else {
829 return EFI_UNSUPPORTED;
830 }
831
832 AddressList = AllocateZeroPool (DataSize);
833 if (AddressList == NULL) {
834 return EFI_OUT_OF_RESOURCES;
835 }
836
837 TmpStr = AddressList;
838
839 NET_LIST_FOR_EACH (Entry, ListHead) {
840 Node = NET_LIST_USER_STRUCT (Entry, IP6_ADDRESS_INFO_ENTRY, Link);
841 if (AddressType == Ip6ConfigNvHostAddress) {
842 ManualAddress = (EFI_IP6_CONFIG_MANUAL_ADDRESS *) AddressList;
843 IP6_COPY_ADDRESS (&ManualAddress->Address, &Node->AddrInfo.Address);
844 ManualAddress->PrefixLength = Node->AddrInfo.PrefixLength;
845 AddressList = (UINT8 *) AddressList + sizeof (EFI_IP6_CONFIG_MANUAL_ADDRESS);
846 } else {
847 Ip6Address = (EFI_IPv6_ADDRESS *) AddressList;
848 IP6_COPY_ADDRESS (Ip6Address, &Node->AddrInfo.Address);
849 AddressList = (UINT8 *) AddressList + sizeof (EFI_IPv6_ADDRESS);
850 }
851 }
852
853 *AddressInfo = TmpStr;
854 *AddressSize = DataSize;
855 return EFI_SUCCESS;
856 }
857
858 /**
859 Convert the IP6 configuration data into the IFR data.
860
861 @param[in, out] IfrNvData The IFR NV data.
862 @param[in] Instance The IP6 config instance data.
863
864 @retval EFI_SUCCESS The operation finished successfully.
865 @retval EFI_INVALID_PARAMETER Any input parameter is invalid.
866 @retval EFI_UNSUPPORTED The policy is not supported in the current implementation.
867 @retval Others Other errors as indicated.
868
869 **/
870 EFI_STATUS
871 Ip6ConvertConfigNvDataToIfrNvData (
872 IN OUT IP6_CONFIG_IFR_NVDATA *IfrNvData,
873 IN IP6_CONFIG_INSTANCE *Instance
874 )
875 {
876 IP6_CONFIG_NVDATA *Ip6NvData;
877 EFI_IP6_CONFIG_PROTOCOL *Ip6Config;
878 UINTN DataSize;
879 VOID *Data;
880 EFI_STATUS Status;
881 EFI_IP6_CONFIG_POLICY Policy;
882 EFI_IP6_CONFIG_DUP_ADDR_DETECT_TRANSMITS DadXmits;
883 EFI_HII_HANDLE HiiHandle;
884
885 if ((IfrNvData == NULL) || (Instance == NULL)) {
886 return EFI_INVALID_PARAMETER;
887 }
888
889 NET_CHECK_SIGNATURE (Instance, IP6_CONFIG_INSTANCE_SIGNATURE);
890
891 Ip6Config = &Instance->Ip6Config;
892 Ip6NvData = &Instance->Ip6NvData;
893 Data = NULL;
894 DataSize = 0;
895 HiiHandle = Instance->CallbackInfo.RegisteredHandle;
896
897 //
898 // Get the current interface info.
899 //
900 Status = Ip6ConfigNvGetData (
901 Ip6Config,
902 Ip6ConfigDataTypeInterfaceInfo,
903 &DataSize,
904 (VOID **) &Data
905 );
906 if (EFI_ERROR (Status)) {
907 goto Exit;
908 }
909
910 //
911 // Convert the interface info to string and print.
912 //
913 Status = Ip6ConvertInterfaceInfoToString (
914 (EFI_IP6_CONFIG_INTERFACE_INFO *) Data,
915 HiiHandle,
916 IfrNvData
917 );
918 if (EFI_ERROR (Status)) {
919 goto Exit;
920 }
921
922 //
923 // Get the interface id.
924 //
925 DataSize = sizeof (EFI_IP6_CONFIG_INTERFACE_ID);
926 ZeroMem (&Ip6NvData->InterfaceId, DataSize);
927 Status = Ip6Config->GetData (
928 Ip6Config,
929 Ip6ConfigDataTypeAltInterfaceId,
930 &DataSize,
931 &Ip6NvData->InterfaceId
932 );
933 if (EFI_ERROR (Status)) {
934 goto Exit;
935 }
936
937 Ip6ConvertInterfaceIdToString (IfrNvData->InterfaceId, &Ip6NvData->InterfaceId);
938
939 //
940 // Get current policy.
941 //
942 DataSize = sizeof (EFI_IP6_CONFIG_POLICY);
943 Status = Ip6Config->GetData (
944 Ip6Config,
945 Ip6ConfigDataTypePolicy,
946 &DataSize,
947 &Policy
948 );
949
950 if (EFI_ERROR (Status)) {
951 goto Exit;
952 }
953
954 if (Policy == Ip6ConfigPolicyManual) {
955 IfrNvData->Policy = IP6_POLICY_MANUAL;
956 } else if (Policy == Ip6ConfigPolicyAutomatic) {
957 IfrNvData->Policy = IP6_POLICY_AUTO;
958 } else {
959 ASSERT (FALSE);
960 Status = EFI_UNSUPPORTED;
961 goto Exit;
962 }
963
964 //
965 // Get Duplicate Address Detection Transmits count.
966 //
967 DataSize = sizeof (EFI_IP6_CONFIG_DUP_ADDR_DETECT_TRANSMITS);
968 Status = Ip6Config->GetData (
969 Ip6Config,
970 Ip6ConfigDataTypeDupAddrDetectTransmits,
971 &DataSize,
972 &DadXmits
973 );
974
975 if (EFI_ERROR (Status)) {
976 goto Exit;
977 }
978
979 IfrNvData->DadTransmitCount = DadXmits.DupAddrDetectTransmits;
980
981 Exit:
982 if (Data != NULL) {
983 FreePool (Data);
984 }
985
986 return Status;
987 }
988
989 /**
990 Convert IFR data into IP6 configuration data. The policy, alternative interface
991 ID, and DAD transmit counts, and will be saved.
992
993 @param[in] IfrNvData The IFR NV data.
994 @param[in, out] Instance The IP6 config instance data.
995
996 @retval EFI_SUCCESS The operation finished successfully.
997 @retval EFI_INVALID_PARAMETER Any input parameter is invalid.
998 @retval Others Other errors as indicated.
999
1000 **/
1001 EFI_STATUS
1002 Ip6ConvertIfrNvDataToConfigNvDataGeneral (
1003 IN IP6_CONFIG_IFR_NVDATA *IfrNvData,
1004 IN OUT IP6_CONFIG_INSTANCE *Instance
1005 )
1006 {
1007 IP6_CONFIG_NVDATA *Ip6NvData;
1008 EFI_IP6_CONFIG_PROTOCOL *Ip6Config;
1009 EFI_STATUS Status;
1010
1011 if ((IfrNvData == NULL) || (Instance == NULL)) {
1012 return EFI_INVALID_PARAMETER;
1013 }
1014
1015 NET_CHECK_SIGNATURE (Instance, IP6_CONFIG_INSTANCE_SIGNATURE);
1016 Ip6NvData = &Instance->Ip6NvData;
1017 Ip6Config = &Instance->Ip6Config;
1018
1019 //
1020 // Update those fields which don't have INTERACTIVE attribute.
1021 //
1022 if (IfrNvData->Policy == IP6_POLICY_AUTO) {
1023 Ip6NvData->Policy = Ip6ConfigPolicyAutomatic;
1024 } else if (IfrNvData->Policy == IP6_POLICY_MANUAL) {
1025 Ip6NvData->Policy = Ip6ConfigPolicyManual;
1026 }
1027
1028 Ip6NvData->DadTransmitCount.DupAddrDetectTransmits = IfrNvData->DadTransmitCount;
1029
1030 //
1031 // Set the configured policy.
1032 //
1033 Status = Ip6Config->SetData (
1034 Ip6Config,
1035 Ip6ConfigDataTypePolicy,
1036 sizeof (EFI_IP6_CONFIG_POLICY),
1037 &Ip6NvData->Policy
1038 );
1039 if (EFI_ERROR (Status)) {
1040 return Status;
1041 }
1042
1043 //
1044 // Set the duplicate address detection transmits count.
1045 //
1046 Status = Ip6Config->SetData (
1047 Ip6Config,
1048 Ip6ConfigDataTypeDupAddrDetectTransmits,
1049 sizeof (EFI_IP6_CONFIG_DUP_ADDR_DETECT_TRANSMITS),
1050 &Ip6NvData->DadTransmitCount
1051 );
1052 if (EFI_ERROR (Status)) {
1053 return Status;
1054 }
1055
1056 //
1057 // Set the alternative interface ID
1058 //
1059 Status = Ip6Config->SetData (
1060 Ip6Config,
1061 Ip6ConfigDataTypeAltInterfaceId,
1062 sizeof (EFI_IP6_CONFIG_INTERFACE_ID),
1063 &Ip6NvData->InterfaceId
1064 );
1065 if (EFI_ERROR (Status)) {
1066 return Status;
1067 }
1068
1069 return EFI_SUCCESS;
1070 }
1071
1072 /**
1073 Convert IFR data into IP6 configuration data. The policy, configured
1074 manual address, gateway address, and DNS server address will be saved.
1075
1076 @param[in] IfrNvData The IFR NV data.
1077 @param[in, out] Instance The IP6 config instance data.
1078
1079 @retval EFI_SUCCESS The operation finished successfully.
1080 @retval EFI_INVALID_PARAMETER Any input parameter is invalid.
1081 @retval Others Other errors as indicated.
1082
1083 **/
1084 EFI_STATUS
1085 Ip6ConvertIfrNvDataToConfigNvDataAdvanced (
1086 IN IP6_CONFIG_IFR_NVDATA *IfrNvData,
1087 IN OUT IP6_CONFIG_INSTANCE *Instance
1088 )
1089 {
1090 IP6_CONFIG_NVDATA *Ip6NvData;
1091 EFI_IP6_CONFIG_PROTOCOL *Ip6Config;
1092 EFI_STATUS Status;
1093 EFI_IP6_CONFIG_MANUAL_ADDRESS *ManualAddress;
1094 EFI_IPv6_ADDRESS *Address;
1095 BOOLEAN IsAddressOk;
1096 EFI_EVENT SetAddressEvent;
1097 EFI_EVENT TimeoutEvent;
1098 UINTN DataSize;
1099
1100 if ((IfrNvData == NULL) || (Instance == NULL)) {
1101 return EFI_INVALID_PARAMETER;
1102 }
1103
1104 if (IfrNvData->Policy == IP6_POLICY_AUTO) {
1105 return EFI_SUCCESS;
1106 }
1107
1108 NET_CHECK_SIGNATURE (Instance, IP6_CONFIG_INSTANCE_SIGNATURE);
1109 Ip6NvData = &Instance->Ip6NvData;
1110 Ip6Config = &Instance->Ip6Config;
1111
1112 //
1113 // Update those fields which don't have INTERACTIVE attribute.
1114 //
1115 Ip6NvData->Policy = Ip6ConfigPolicyManual;
1116
1117 //
1118 // Set the configured policy.
1119 //
1120 Status = Ip6Config->SetData (
1121 Ip6Config,
1122 Ip6ConfigDataTypePolicy,
1123 sizeof (EFI_IP6_CONFIG_POLICY),
1124 &Ip6NvData->Policy
1125 );
1126 if (EFI_ERROR (Status)) {
1127 return Status;
1128 }
1129
1130 //
1131 // Create events & timers for asynchronous settings.
1132 //
1133 SetAddressEvent = NULL;
1134 TimeoutEvent = NULL;
1135 ManualAddress = NULL;
1136 Address = NULL;
1137
1138 Status = gBS->CreateEvent (
1139 EVT_NOTIFY_SIGNAL,
1140 TPL_NOTIFY,
1141 Ip6ConfigManualAddressNotify,
1142 &IsAddressOk,
1143 &SetAddressEvent
1144 );
1145 if (EFI_ERROR (Status)) {
1146 goto Exit;
1147 }
1148
1149 Status = gBS->CreateEvent (
1150 EVT_TIMER,
1151 TPL_CALLBACK,
1152 NULL,
1153 NULL,
1154 &TimeoutEvent
1155 );
1156 if (EFI_ERROR (Status)) {
1157 goto Exit;
1158 }
1159
1160 //
1161 // Set the manual address list. This is an asynchronous process.
1162 //
1163 if (!IsListEmpty (&Ip6NvData->ManualAddress) && (Ip6NvData->ManualAddressCount != 0)) {
1164 Status = Ip6BuildNvAddressInfo (
1165 Instance,
1166 Ip6ConfigNvHostAddress,
1167 (VOID **) &ManualAddress,
1168 &DataSize
1169 );
1170 if (EFI_ERROR (Status)) {
1171 goto Exit;
1172 }
1173
1174 IsAddressOk = FALSE;
1175
1176 Status = Ip6Config->RegisterDataNotify (
1177 Ip6Config,
1178 Ip6ConfigDataTypeManualAddress,
1179 SetAddressEvent
1180 );
1181 if (EFI_ERROR (Status)) {
1182 goto Exit;
1183 }
1184
1185 Status = Ip6Config->SetData (
1186 Ip6Config,
1187 Ip6ConfigDataTypeManualAddress,
1188 DataSize,
1189 (VOID *) ManualAddress
1190 );
1191 if (Status == EFI_NOT_READY) {
1192 gBS->SetTimer (TimeoutEvent, TimerRelative, 50000000);
1193 while (EFI_ERROR (gBS->CheckEvent (TimeoutEvent))) {
1194 if (IsAddressOk) {
1195 Status = EFI_SUCCESS;
1196 }
1197 break;
1198 }
1199 }
1200
1201 Status = Ip6Config->UnregisterDataNotify (
1202 Ip6Config,
1203 Ip6ConfigDataTypeManualAddress,
1204 SetAddressEvent
1205 );
1206 if (EFI_ERROR (Status)) {
1207 goto Exit;
1208 }
1209 }
1210
1211 //
1212 // Set gateway address list.
1213 //
1214 if (!IsListEmpty (&Ip6NvData->GatewayAddress) && (Ip6NvData->GatewayAddressCount != 0)) {
1215 Status = Ip6BuildNvAddressInfo (
1216 Instance,
1217 Ip6ConfigNvGatewayAddress,
1218 (VOID **) &Address,
1219 &DataSize
1220 );
1221 if (EFI_ERROR (Status)) {
1222 goto Exit;
1223 }
1224
1225 Status = Ip6Config->SetData (
1226 Ip6Config,
1227 Ip6ConfigDataTypeGateway,
1228 DataSize,
1229 (VOID *) Address
1230 );
1231 if (EFI_ERROR (Status)) {
1232 goto Exit;
1233 }
1234
1235 FreePool (Address);
1236 Address = NULL;
1237 }
1238
1239 //
1240 // Set DNS server address list.
1241 //
1242 if (!IsListEmpty (&Ip6NvData->DnsAddress) && (Ip6NvData->DnsAddressCount != 0)) {
1243 Status = Ip6BuildNvAddressInfo (
1244 Instance,
1245 Ip6ConfigNvDnsAddress,
1246 (VOID **) &Address,
1247 &DataSize
1248 );
1249 if (EFI_ERROR (Status)) {
1250 goto Exit;
1251 }
1252
1253 Status = Ip6Config->SetData (
1254 Ip6Config,
1255 Ip6ConfigDataTypeDnsServer,
1256 DataSize,
1257 (VOID *) Address
1258 );
1259 if (EFI_ERROR (Status)) {
1260 goto Exit;
1261 }
1262 }
1263
1264 Status = EFI_SUCCESS;
1265
1266 Exit:
1267 if (SetAddressEvent != NULL) {
1268 gBS->CloseEvent (SetAddressEvent);
1269 }
1270
1271 if (TimeoutEvent != NULL) {
1272 gBS->CloseEvent (TimeoutEvent);
1273 }
1274
1275 if (ManualAddress != NULL) {
1276 FreePool (ManualAddress);
1277 }
1278
1279 if (Address != NULL) {
1280 FreePool (Address);
1281 }
1282
1283 return Status;
1284 }
1285
1286
1287 /**
1288 This function allows the caller to request the current
1289 configuration for one or more named elements. The resulting
1290 string is in <ConfigAltResp> format. Any and all alternative
1291 configuration strings shall also be appended to the end of the
1292 current configuration string. If they are, they must appear
1293 after the current configuration. They must contain the same
1294 routing (GUID, NAME, PATH) as the current configuration string.
1295 They must have an additional description indicating the type of
1296 alternative configuration the string represents,
1297 "ALTCFG=<StringToken>". That <StringToken> (when
1298 converted from Hex UNICODE to binary) is a reference to a
1299 string in the associated string pack.
1300
1301 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
1302 @param[in] Request A null-terminated Unicode string in
1303 <ConfigRequest> format. Note that this
1304 includes the routing information as well as
1305 the configurable name / value pairs. It is
1306 invalid for this string to be in
1307 <MultiConfigRequest> format.
1308 @param[out] Progress On return, points to a character in the
1309 Request string. Points to the string's null
1310 terminator if request was successful. Points
1311 to the most recent "&" before the first
1312 failing name / value pair (or the beginning
1313 of the string if the failure is in the first
1314 name / value pair) if the request was not
1315 successful.
1316 @param[out] Results A null-terminated Unicode string in
1317 <ConfigAltResp> format which has all values
1318 filled in for the names in the Request string.
1319 String to be allocated by the called function.
1320
1321 @retval EFI_SUCCESS The Results string is filled with the
1322 values corresponding to all requested
1323 names.
1324 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the
1325 parts of the results that must be
1326 stored awaiting possible future
1327 protocols.
1328 @retval EFI_INVALID_PARAMETER For example, passing in a NULL
1329 for the Request parameter
1330 would result in this type of
1331 error. In this case, the
1332 Progress parameter would be
1333 set to NULL.
1334 @retval EFI_NOT_FOUND Routing data doesn't match any
1335 known driver. Progress set to the
1336 first character in the routing header.
1337 Note: There is no requirement that the
1338 driver validate the routing data. It
1339 must skip the <ConfigHdr> in order to
1340 process the names.
1341 @retval EFI_INVALID_PARAMETER Illegal syntax. Progress set
1342 to most recent & before the
1343 error or the beginning of the
1344 string.
1345 @retval EFI_INVALID_PARAMETER Unknown name. Progress points
1346 to the & before the name in
1347 question. Currently not implemented.
1348 **/
1349 EFI_STATUS
1350 EFIAPI
1351 Ip6FormExtractConfig (
1352 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
1353 IN CONST EFI_STRING Request,
1354 OUT EFI_STRING *Progress,
1355 OUT EFI_STRING *Results
1356 )
1357 {
1358
1359 EFI_STATUS Status;
1360 IP6_FORM_CALLBACK_INFO *Private;
1361 IP6_CONFIG_INSTANCE *Ip6ConfigInstance;
1362 IP6_CONFIG_IFR_NVDATA *IfrNvData;
1363 EFI_STRING ConfigRequestHdr;
1364 EFI_STRING ConfigRequest;
1365 BOOLEAN AllocatedRequest;
1366 UINTN Size;
1367 UINTN BufferSize;
1368
1369 if (This == NULL || Progress == NULL || Results == NULL) {
1370 return EFI_INVALID_PARAMETER;
1371 }
1372
1373 *Progress = Request;
1374 if ((Request != NULL) &&
1375 !HiiIsConfigHdrMatch (Request, &gIp6ConfigNvDataGuid, mIp6ConfigStorageName)) {
1376 return EFI_NOT_FOUND;
1377 }
1378
1379 ConfigRequestHdr = NULL;
1380 ConfigRequest = NULL;
1381 AllocatedRequest = FALSE;
1382 Size = 0;
1383
1384 Private = IP6_FORM_CALLBACK_INFO_FROM_CONFIG_ACCESS (This);
1385 Ip6ConfigInstance = IP6_CONFIG_INSTANCE_FROM_FORM_CALLBACK (Private);
1386 BufferSize = sizeof (IP6_CONFIG_IFR_NVDATA);
1387
1388 IfrNvData = (IP6_CONFIG_IFR_NVDATA *) AllocateZeroPool (BufferSize);
1389 if (IfrNvData == NULL) {
1390 return EFI_OUT_OF_RESOURCES;
1391 }
1392
1393 Status = Ip6ConvertConfigNvDataToIfrNvData (IfrNvData, Ip6ConfigInstance);
1394 if (EFI_ERROR (Status)) {
1395 goto Exit;
1396 }
1397
1398 ConfigRequest = Request;
1399 if ((Request == NULL) || (StrStr (Request, L"OFFSET") == NULL)) {
1400 //
1401 // Request has no request element, construct full request string.
1402 // Allocate and fill a buffer large enough to hold the <ConfigHdr> template
1403 // followed by "&OFFSET=0&WIDTH=WWWWWWWWWWWWWWWW" followed by a Null-terminator.
1404 //
1405 ConfigRequestHdr = HiiConstructConfigHdr (
1406 &gIp6ConfigNvDataGuid,
1407 mIp6ConfigStorageName,
1408 Private->ChildHandle
1409 );
1410 Size = (StrLen (ConfigRequestHdr) + 32 + 1) * sizeof (CHAR16);
1411 ConfigRequest = AllocateZeroPool (Size);
1412 ASSERT (ConfigRequest != NULL);
1413 AllocatedRequest = TRUE;
1414 UnicodeSPrint (
1415 ConfigRequest,
1416 Size,
1417 L"%s&OFFSET=0&WIDTH=%016LX",
1418 ConfigRequestHdr,
1419 (UINT64) BufferSize
1420 );
1421 FreePool (ConfigRequestHdr);
1422 }
1423
1424 //
1425 // Convert buffer data to <ConfigResp> by helper function BlockToConfig()
1426 //
1427 Status = gHiiConfigRouting->BlockToConfig (
1428 gHiiConfigRouting,
1429 ConfigRequest,
1430 (UINT8 *) IfrNvData,
1431 BufferSize,
1432 Results,
1433 Progress
1434 );
1435
1436 Exit:
1437 FreePool (IfrNvData);
1438 //
1439 // Free the allocated config request string.
1440 //
1441 if (AllocatedRequest) {
1442 FreePool (ConfigRequest);
1443 ConfigRequest = NULL;
1444 }
1445 //
1446 // Set Progress string to the original request string.
1447 //
1448 if (Request == NULL) {
1449 *Progress = NULL;
1450 } else if (StrStr (Request, L"OFFSET") == NULL) {
1451 *Progress = Request + StrLen (Request);
1452 }
1453
1454 return Status;
1455 }
1456
1457 /**
1458 This function applies changes in a driver's configuration.
1459 Input is a Configuration, which has the routing data for this
1460 driver followed by name / value configuration pairs. The driver
1461 must apply those pairs to its configurable storage. If the
1462 driver's configuration is stored in a linear block of data
1463 and the driver's name / value pairs are in <BlockConfig>
1464 format, it may use the ConfigToBlock helper function (above) to
1465 simplify the job. Currently not implemented.
1466
1467 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
1468 @param[in] Configuration A null-terminated Unicode string in
1469 <ConfigString> format.
1470 @param[out] Progress A pointer to a string filled in with the
1471 offset of the most recent '&' before the
1472 first failing name / value pair (or the
1473 beginn ing of the string if the failure
1474 is in the first name / value pair) or
1475 the terminating NULL if all was
1476 successful.
1477
1478 @retval EFI_SUCCESS The results have been distributed or are
1479 awaiting distribution.
1480 @retval EFI_OUT_OF_MEMORY Not enough memory to store the
1481 parts of the results that must be
1482 stored awaiting possible future
1483 protocols.
1484 @retval EFI_INVALID_PARAMETERS Passing in a NULL for the
1485 Results parameter would result
1486 in this type of error.
1487 @retval EFI_NOT_FOUND Target for the specified routing data
1488 was not found.
1489 **/
1490 EFI_STATUS
1491 EFIAPI
1492 Ip6FormRouteConfig (
1493 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
1494 IN CONST EFI_STRING Configuration,
1495 OUT EFI_STRING *Progress
1496 )
1497 {
1498 if (This == NULL || Configuration == NULL || Progress == NULL) {
1499 return EFI_INVALID_PARAMETER;
1500 }
1501
1502 //
1503 // Check routing data in <ConfigHdr>.
1504 // Note: if only one Storage is used, then this checking could be skipped.
1505 //
1506 if (!HiiIsConfigHdrMatch (Configuration, &gIp6ConfigNvDataGuid, mIp6ConfigStorageName)) {
1507 *Progress = Configuration;
1508 return EFI_NOT_FOUND;
1509 }
1510
1511 *Progress = Configuration + StrLen (Configuration);
1512
1513 return EFI_SUCCESS;
1514 }
1515
1516 /**
1517 Display host addresses, route table, DNS addresses and gateway addresses in
1518 "IPv6 Current Setting" page.
1519
1520 @param[in] Instance The IP6 config instance data.
1521
1522 @retval EFI_SUCCESS The operation finished successfully.
1523 @retval Others Other errors as indicated.
1524
1525 **/
1526 EFI_STATUS
1527 Ip6GetCurrentSetting (
1528 IN IP6_CONFIG_INSTANCE *Instance
1529 )
1530 {
1531 EFI_IP6_CONFIG_PROTOCOL *Ip6Config;
1532 EFI_HII_HANDLE HiiHandle;
1533 EFI_IP6_CONFIG_INTERFACE_INFO *Data;
1534 UINTN DataSize;
1535 EFI_STATUS Status;
1536 CHAR16 PortString[ADDRESS_STR_MAX_SIZE];
1537 EFI_IP6_CONFIG_INTERFACE_INFO *IfInfo;
1538
1539
1540 Ip6Config = &Instance->Ip6Config;
1541 HiiHandle = Instance->CallbackInfo.RegisteredHandle;
1542 Data = NULL;
1543
1544 //
1545 // Get current interface info.
1546 //
1547 Status = Ip6ConfigNvGetData (
1548 Ip6Config,
1549 Ip6ConfigDataTypeInterfaceInfo,
1550 &DataSize,
1551 (VOID **) &Data
1552 );
1553 if (EFI_ERROR (Status)) {
1554 return Status;
1555 }
1556
1557 //
1558 // Generate dynamic text opcode for host address and draw it.
1559 //
1560 IfInfo = (EFI_IP6_CONFIG_INTERFACE_INFO *) Data;
1561 Status = Ip6ConvertAddressListToString (
1562 PortString,
1563 HiiHandle,
1564 Ip6ConfigNvHostAddress,
1565 IfInfo->AddressInfo,
1566 IfInfo->AddressInfoCount
1567 );
1568 if (EFI_ERROR (Status)) {
1569 FreePool (Data);
1570 return Status;
1571 }
1572
1573 //
1574 // Generate the dynamic text opcode for route table and draw it.
1575 //
1576 Status = Ip6ConvertAddressListToString (
1577 PortString,
1578 HiiHandle,
1579 Ip6ConfigNvRouteTable,
1580 IfInfo->RouteTable,
1581 IfInfo->RouteCount
1582 );
1583 if (EFI_ERROR (Status)) {
1584 FreePool (Data);
1585 return Status;
1586 }
1587
1588 //
1589 // Get DNS server list.
1590 //
1591 FreePool (Data);
1592 DataSize = 0;
1593 Data = NULL;
1594 Status = Ip6ConfigNvGetData (
1595 Ip6Config,
1596 Ip6ConfigDataTypeDnsServer,
1597 &DataSize,
1598 (VOID **) &Data
1599 );
1600 if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) {
1601 if (Data != NULL) {
1602 FreePool (Data);
1603 }
1604 return Status;
1605 }
1606
1607 if (DataSize > 0) {
1608 //
1609 // Generate the dynamic text opcode for DNS server and draw it.
1610 //
1611 Status = Ip6ConvertAddressListToString (
1612 PortString,
1613 HiiHandle,
1614 Ip6ConfigNvDnsAddress,
1615 Data,
1616 DataSize / sizeof (EFI_IPv6_ADDRESS)
1617 );
1618 if (EFI_ERROR (Status)) {
1619 FreePool (Data);
1620 return Status;
1621 }
1622 }
1623
1624 //
1625 // Get gateway adderss list.
1626 //
1627 if (Data != NULL) {
1628 FreePool (Data);
1629 }
1630
1631 DataSize = 0;
1632 Data = NULL;
1633 Status = Ip6ConfigNvGetData (
1634 Ip6Config,
1635 Ip6ConfigDataTypeGateway,
1636 &DataSize,
1637 (VOID **) &Data
1638 );
1639 if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) {
1640 if (Data != NULL) {
1641 FreePool (Data);
1642 }
1643 return Status;
1644 }
1645
1646 if (DataSize > 0) {
1647 //
1648 // Generate the dynamic text opcode for gateway and draw it.
1649 //
1650 Status = Ip6ConvertAddressListToString (
1651 PortString,
1652 HiiHandle,
1653 Ip6ConfigNvGatewayAddress,
1654 Data,
1655 DataSize / sizeof (EFI_IPv6_ADDRESS)
1656 );
1657 if (EFI_ERROR (Status)) {
1658 FreePool (Data);
1659 return Status;
1660 }
1661 }
1662
1663 if (Data != NULL) {
1664 FreePool (Data);
1665 }
1666
1667 return EFI_SUCCESS;
1668 }
1669
1670 /**
1671 This function is called to provide results data to the driver.
1672 This data consists of a unique key that is used to identify
1673 which data is either being passed back or being asked for.
1674
1675 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
1676 @param[in] Action Specifies the type of action taken by the browser.
1677 @param[in] QuestionId A unique value which is sent to the original
1678 exporting driver so that it can identify the type
1679 of data to expect. The format of the data tends to
1680 vary based on the opcode that generated the callback.
1681 @param[in] Type The type of value for the question.
1682 @param[in] Value A pointer to the data being sent to the original
1683 exporting driver.
1684 @param[out] ActionRequest On return, points to the action requested by the
1685 callback function.
1686
1687 @retval EFI_SUCCESS The callback successfully handled the action.
1688 @retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the
1689 variable and its data.
1690 @retval EFI_DEVICE_ERROR The variable could not be saved.
1691 @retval EFI_UNSUPPORTED The specified Action is not supported by the
1692 callback. Currently not implemented.
1693 @retval EFI_INVALID_PARAMETER Passed in the wrong parameter.
1694 @retval Others Other errors as indicated.
1695
1696 **/
1697 EFI_STATUS
1698 EFIAPI
1699 Ip6FormCallback (
1700 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
1701 IN EFI_BROWSER_ACTION Action,
1702 IN EFI_QUESTION_ID QuestionId,
1703 IN UINT8 Type,
1704 IN EFI_IFR_TYPE_VALUE *Value,
1705 OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest
1706 )
1707 {
1708 IP6_FORM_CALLBACK_INFO *Private;
1709 UINTN BufferSize;
1710 IP6_CONFIG_IFR_NVDATA *IfrNvData;
1711 EFI_STATUS Status;
1712 EFI_INPUT_KEY Key;
1713 IP6_CONFIG_INSTANCE *Instance;
1714 IP6_CONFIG_NVDATA *Ip6NvData;
1715
1716 if (This == NULL) {
1717 return EFI_INVALID_PARAMETER;
1718 }
1719
1720 Private = IP6_FORM_CALLBACK_INFO_FROM_CONFIG_ACCESS (This);
1721 Instance = IP6_CONFIG_INSTANCE_FROM_FORM_CALLBACK (Private);
1722 Ip6NvData = &Instance->Ip6NvData;
1723
1724 if ((Action == EFI_BROWSER_ACTION_FORM_OPEN) || (Action == EFI_BROWSER_ACTION_FORM_CLOSE)){
1725 return EFI_SUCCESS;
1726 }
1727
1728 if (Action != EFI_BROWSER_ACTION_CHANGING && Action != EFI_BROWSER_ACTION_CHANGED) {
1729 return EFI_UNSUPPORTED;
1730 }
1731
1732 if ((Value == NULL) || (ActionRequest == NULL)) {
1733 return EFI_INVALID_PARAMETER;
1734 }
1735
1736 //
1737 // Retrieve uncommitted data from Browser
1738 //
1739
1740 BufferSize = sizeof (IP6_CONFIG_IFR_NVDATA);
1741 IfrNvData = AllocateZeroPool (BufferSize);
1742 if (IfrNvData == NULL) {
1743 return EFI_OUT_OF_RESOURCES;
1744 }
1745
1746 Status = EFI_SUCCESS;
1747
1748 HiiGetBrowserData (NULL, NULL, BufferSize, (UINT8 *) IfrNvData);
1749
1750 if (Action == EFI_BROWSER_ACTION_CHANGING) {
1751 switch (QuestionId) {
1752 case KEY_GET_CURRENT_SETTING:
1753 Status = Ip6GetCurrentSetting (Instance);
1754 break;
1755
1756 default:
1757 break;
1758 }
1759 } else if (Action == EFI_BROWSER_ACTION_CHANGED) {
1760 switch (QuestionId) {
1761 case KEY_SAVE_CONFIG_CHANGES:
1762 Status = Ip6ConvertIfrNvDataToConfigNvDataAdvanced (IfrNvData, Instance);
1763 if (EFI_ERROR (Status)) {
1764 break;
1765 }
1766
1767 Status = Ip6GetCurrentSetting (Instance);
1768
1769 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_SUBMIT_EXIT;
1770 break;
1771
1772 case KEY_IGNORE_CONFIG_CHANGES:
1773 Ip6FreeAddressInfoList (&Ip6NvData->ManualAddress);
1774 Ip6FreeAddressInfoList (&Ip6NvData->GatewayAddress);
1775 Ip6FreeAddressInfoList (&Ip6NvData->DnsAddress);
1776
1777 Ip6NvData->ManualAddressCount = 0;
1778 Ip6NvData->GatewayAddressCount = 0;
1779 Ip6NvData->DnsAddressCount = 0;
1780
1781 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_DISCARD_EXIT;
1782 break;
1783
1784 case KEY_SAVE_CHANGES:
1785 Status = Ip6ConvertIfrNvDataToConfigNvDataGeneral (IfrNvData, Instance);
1786 if (EFI_ERROR (Status)) {
1787 break;
1788 }
1789 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_SUBMIT;
1790 break;
1791
1792 case KEY_INTERFACE_ID:
1793 Status = Ip6ParseInterfaceIdFromString (IfrNvData->InterfaceId, &Ip6NvData->InterfaceId);
1794 if (EFI_ERROR (Status)) {
1795 CreatePopUp (
1796 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
1797 &Key,
1798 L"Invalid Interface ID!",
1799 NULL
1800 );
1801 }
1802
1803 break;
1804
1805 case KEY_MANUAL_ADDRESS:
1806 Status = Ip6ParseAddressListFromString (
1807 IfrNvData->ManualAddress,
1808 &Ip6NvData->ManualAddress,
1809 &Ip6NvData->ManualAddressCount
1810 );
1811 if (EFI_ERROR (Status)) {
1812 CreatePopUp (
1813 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
1814 &Key,
1815 L"Invalid Host Addresses!",
1816 NULL
1817 );
1818 }
1819
1820 break;
1821
1822 case KEY_GATEWAY_ADDRESS:
1823 Status = Ip6ParseAddressListFromString (
1824 IfrNvData->GatewayAddress,
1825 &Ip6NvData->GatewayAddress,
1826 &Ip6NvData->GatewayAddressCount
1827 );
1828 if (EFI_ERROR (Status)) {
1829 CreatePopUp (
1830 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
1831 &Key,
1832 L"Invalid Gateway Addresses!",
1833 NULL
1834 );
1835 }
1836
1837 break;
1838
1839 case KEY_DNS_ADDRESS:
1840 Status = Ip6ParseAddressListFromString (
1841 IfrNvData->DnsAddress,
1842 &Ip6NvData->DnsAddress,
1843 &Ip6NvData->DnsAddressCount
1844 );
1845 if (EFI_ERROR (Status)) {
1846 CreatePopUp (
1847 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
1848 &Key,
1849 L"Invalid DNS Addresses!",
1850 NULL
1851 );
1852 }
1853
1854 break;
1855
1856 default:
1857 break;
1858 }
1859 }
1860
1861 if (!EFI_ERROR (Status)) {
1862 //
1863 // Pass changed uncommitted data back to Form Browser.
1864 //
1865 BufferSize = sizeof (IP6_CONFIG_IFR_NVDATA);
1866 HiiSetBrowserData (NULL, NULL, BufferSize, (UINT8 *) IfrNvData, NULL);
1867 }
1868
1869 FreePool (IfrNvData);
1870 return Status;
1871 }
1872
1873 /**
1874 Install HII Config Access protocol for network device and allocate resources.
1875
1876 @param[in, out] Instance The IP6_CONFIG_INSTANCE to create a form.
1877
1878 @retval EFI_SUCCESS The HII Config Access protocol is installed.
1879 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
1880 @retval Others Other errors as indicated.
1881
1882 **/
1883 EFI_STATUS
1884 Ip6ConfigFormInit (
1885 IN OUT IP6_CONFIG_INSTANCE *Instance
1886 )
1887 {
1888 EFI_STATUS Status;
1889 IP6_SERVICE *IpSb;
1890 IP6_FORM_CALLBACK_INFO *CallbackInfo;
1891 EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;
1892 VENDOR_DEVICE_PATH VendorDeviceNode;
1893 EFI_SERVICE_BINDING_PROTOCOL *MnpSb;
1894 CHAR16 *MacString;
1895 CHAR16 MenuString[128];
1896 CHAR16 PortString[128];
1897 CHAR16 *OldMenuString;
1898 EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;
1899
1900 IpSb = IP6_SERVICE_FROM_IP6_CONFIG_INSTANCE (Instance);
1901 ASSERT (IpSb != NULL);
1902
1903 Status = gBS->HandleProtocol (
1904 IpSb->Controller,
1905 &gEfiDevicePathProtocolGuid,
1906 (VOID **) &ParentDevicePath
1907 );
1908 if (EFI_ERROR (Status)) {
1909 return Status;
1910 }
1911
1912 CallbackInfo = &Instance->CallbackInfo;
1913 CallbackInfo->Signature = IP6_FORM_CALLBACK_INFO_SIGNATURE;
1914
1915 //
1916 // Construct device path node for EFI HII Config Access protocol,
1917 // which consists of controller physical device path and one hardware
1918 // vendor guid node.
1919 //
1920 ZeroMem (&VendorDeviceNode, sizeof (VENDOR_DEVICE_PATH));
1921 VendorDeviceNode.Header.Type = HARDWARE_DEVICE_PATH;
1922 VendorDeviceNode.Header.SubType = HW_VENDOR_DP;
1923
1924 CopyGuid (&VendorDeviceNode.Guid, &gEfiCallerIdGuid);
1925
1926 SetDevicePathNodeLength (&VendorDeviceNode.Header, sizeof (VENDOR_DEVICE_PATH));
1927 CallbackInfo->HiiVendorDevicePath = AppendDevicePathNode (
1928 ParentDevicePath,
1929 (EFI_DEVICE_PATH_PROTOCOL *) &VendorDeviceNode
1930 );
1931 if (CallbackInfo->HiiVendorDevicePath == NULL) {
1932 Status = EFI_OUT_OF_RESOURCES;
1933 goto Error;
1934 }
1935
1936 ConfigAccess = &CallbackInfo->HiiConfigAccess;
1937 ConfigAccess->ExtractConfig = Ip6FormExtractConfig;
1938 ConfigAccess->RouteConfig = Ip6FormRouteConfig;
1939 ConfigAccess->Callback = Ip6FormCallback;
1940
1941 //
1942 // Install Device Path Protocol and Config Access protocol on new handle
1943 //
1944 Status = gBS->InstallMultipleProtocolInterfaces (
1945 &CallbackInfo->ChildHandle,
1946 &gEfiDevicePathProtocolGuid,
1947 CallbackInfo->HiiVendorDevicePath,
1948 &gEfiHiiConfigAccessProtocolGuid,
1949 ConfigAccess,
1950 NULL
1951 );
1952 if (!EFI_ERROR (Status)) {
1953 //
1954 // Open the Parent Handle for the child
1955 //
1956 Status = gBS->OpenProtocol (
1957 IpSb->Controller,
1958 &gEfiManagedNetworkServiceBindingProtocolGuid,
1959 (VOID **) &MnpSb,
1960 IpSb->Image,
1961 CallbackInfo->ChildHandle,
1962 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
1963 );
1964 }
1965
1966 if (EFI_ERROR (Status)) {
1967 goto Error;
1968 }
1969
1970 //
1971 // Publish our HII data
1972 //
1973 CallbackInfo->RegisteredHandle = HiiAddPackages (
1974 &gIp6ConfigNvDataGuid,
1975 CallbackInfo->ChildHandle,
1976 Ip6DxeStrings,
1977 Ip6ConfigBin,
1978 NULL
1979 );
1980 if (CallbackInfo->RegisteredHandle == NULL) {
1981 Status = EFI_OUT_OF_RESOURCES;
1982 goto Error;
1983 }
1984
1985 //
1986 // Append MAC string in the menu help string and tile help string
1987 //
1988 Status = NetLibGetMacString (IpSb->Controller, IpSb->Image, &MacString);
1989 if (!EFI_ERROR (Status)) {
1990 OldMenuString = HiiGetString (
1991 CallbackInfo->RegisteredHandle,
1992 STRING_TOKEN (STR_IP6_CONFIG_FORM_HELP),
1993 NULL)
1994 ;
1995 UnicodeSPrint (MenuString, 128, L"%s (MAC:%s)", OldMenuString, MacString);
1996 HiiSetString (
1997 CallbackInfo->RegisteredHandle,
1998 STRING_TOKEN (STR_IP6_CONFIG_FORM_HELP),
1999 MenuString,
2000 NULL
2001 );
2002 UnicodeSPrint (PortString, 128, L"MAC:%s", MacString);
2003 HiiSetString (
2004 CallbackInfo->RegisteredHandle,
2005 STRING_TOKEN (STR_IP6_DEVICE_FORM_HELP),
2006 PortString,
2007 NULL
2008 );
2009
2010 FreePool (MacString);
2011 FreePool (OldMenuString);
2012
2013 InitializeListHead (&Instance->Ip6NvData.ManualAddress);
2014 InitializeListHead (&Instance->Ip6NvData.GatewayAddress);
2015 InitializeListHead (&Instance->Ip6NvData.DnsAddress);
2016
2017 return EFI_SUCCESS;
2018 }
2019
2020 Error:
2021 Ip6ConfigFormUnload (Instance);
2022 return Status;
2023 }
2024
2025 /**
2026 Uninstall the HII Config Access protocol for network devices and free up the resources.
2027
2028 @param[in, out] Instance The IP6_CONFIG_INSTANCE to unload a form.
2029
2030 **/
2031 VOID
2032 Ip6ConfigFormUnload (
2033 IN OUT IP6_CONFIG_INSTANCE *Instance
2034 )
2035 {
2036 IP6_SERVICE *IpSb;
2037 IP6_FORM_CALLBACK_INFO *CallbackInfo;
2038 IP6_CONFIG_NVDATA *Ip6NvData;
2039
2040 IpSb = IP6_SERVICE_FROM_IP6_CONFIG_INSTANCE (Instance);
2041 ASSERT (IpSb != NULL);
2042
2043 CallbackInfo = &Instance->CallbackInfo;
2044
2045 if (CallbackInfo->ChildHandle != NULL) {
2046
2047 //
2048 // Close the child handle
2049 //
2050 gBS->CloseProtocol (
2051 IpSb->Controller,
2052 &gEfiManagedNetworkServiceBindingProtocolGuid,
2053 IpSb->Image,
2054 CallbackInfo->ChildHandle
2055 );
2056 //
2057 // Uninstall EFI_HII_CONFIG_ACCESS_PROTOCOL
2058 //
2059 gBS->UninstallMultipleProtocolInterfaces (
2060 CallbackInfo->ChildHandle,
2061 &gEfiDevicePathProtocolGuid,
2062 CallbackInfo->HiiVendorDevicePath,
2063 &gEfiHiiConfigAccessProtocolGuid,
2064 &CallbackInfo->HiiConfigAccess,
2065 NULL
2066 );
2067 }
2068
2069 if (CallbackInfo->HiiVendorDevicePath != NULL) {
2070 FreePool (CallbackInfo->HiiVendorDevicePath);
2071 }
2072
2073 if (CallbackInfo->RegisteredHandle != NULL) {
2074 //
2075 // Remove HII package list
2076 //
2077 HiiRemovePackages (CallbackInfo->RegisteredHandle);
2078 }
2079
2080 Ip6NvData = &Instance->Ip6NvData;
2081
2082 Ip6FreeAddressInfoList (&Ip6NvData->ManualAddress);
2083 Ip6FreeAddressInfoList (&Ip6NvData->GatewayAddress);
2084 Ip6FreeAddressInfoList (&Ip6NvData->DnsAddress);
2085
2086 Ip6NvData->ManualAddressCount = 0;
2087 Ip6NvData->GatewayAddressCount = 0;
2088 Ip6NvData->DnsAddressCount = 0;
2089 }